mirror of
https://github.com/1dot13/source.git
synced 2026-09-09 14:46:05 +02:00
Updated Enemy Taunts (by anv)
- fixed crash due to same enemy taunting several times in a row (e.g. after being hit by a burst) - prevent enemy from taunting again, before his previous taunt is finished - taunt .xmls should be kept in subdirectory TableData\EnemyTaunts\ to avoid mess in TableData\ - added <szCensoredText>, if TAUNT_CENSORED_MODE set to TRUE and <szCensoredText> defined, it will be displayed instead of <szText> git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6659 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -3206,6 +3206,7 @@ void LoadCTHConstants()
|
|||||||
void LoadTauntsSettings()
|
void LoadTauntsSettings()
|
||||||
{
|
{
|
||||||
CIniReader iniReader(TAUNTS_SETTINGS_FILE);
|
CIniReader iniReader(TAUNTS_SETTINGS_FILE);
|
||||||
|
gTauntsSettings.fTauntCensoredMode = iniReader.ReadBoolean("Taunts Settings","TAUNT_CENSORED_MODE", FALSE );
|
||||||
gTauntsSettings.fTauntShowPopupBox = iniReader.ReadBoolean("Taunts Settings","TAUNT_SHOW_POPUP_BOX", TRUE );
|
gTauntsSettings.fTauntShowPopupBox = iniReader.ReadBoolean("Taunts Settings","TAUNT_SHOW_POPUP_BOX", TRUE );
|
||||||
gTauntsSettings.fTauntShowInLog = iniReader.ReadBoolean("Taunts Settings","TAUNT_SHOW_IN_LOG", TRUE );
|
gTauntsSettings.fTauntShowInLog = iniReader.ReadBoolean("Taunts Settings","TAUNT_SHOW_IN_LOG", TRUE );
|
||||||
gTauntsSettings.fTauntMakeNoise = iniReader.ReadBoolean("Taunts Settings","TAUNT_MAKE_NOISE", TRUE );
|
gTauntsSettings.fTauntMakeNoise = iniReader.ReadBoolean("Taunts Settings","TAUNT_MAKE_NOISE", TRUE );
|
||||||
|
|||||||
@@ -1330,6 +1330,7 @@ typedef struct
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
BOOLEAN fTauntCensoredMode;
|
||||||
BOOLEAN fTauntShowPopupBox;
|
BOOLEAN fTauntShowPopupBox;
|
||||||
BOOLEAN fTauntShowInLog;
|
BOOLEAN fTauntShowInLog;
|
||||||
BOOLEAN fTauntMakeNoise;
|
BOOLEAN fTauntMakeNoise;
|
||||||
|
|||||||
+70
-36
@@ -45,6 +45,8 @@
|
|||||||
#define HIGH_TOWN_LOYALTY 80
|
#define HIGH_TOWN_LOYALTY 80
|
||||||
#define CIV_QUOTE_HINT 99
|
#define CIV_QUOTE_HINT 99
|
||||||
|
|
||||||
|
#define MAX_APPLICABLE_TAUNTS 512
|
||||||
|
|
||||||
extern void CaptureTimerCallback( void );
|
extern void CaptureTimerCallback( void );
|
||||||
|
|
||||||
BOOLEAN gfSurrendered = FALSE;
|
BOOLEAN gfSurrendered = FALSE;
|
||||||
@@ -137,6 +139,11 @@ CHAR16 gzCivQuote[ 320 ];
|
|||||||
UINT16 gusCivQuoteBoxWidth;
|
UINT16 gusCivQuoteBoxWidth;
|
||||||
UINT16 gusCivQuoteBoxHeight;
|
UINT16 gusCivQuoteBoxHeight;
|
||||||
|
|
||||||
|
// anv: store times, when enemy taunt will be finished (so they won't taunt 50 times / second)
|
||||||
|
UINT32 uiTauntFinishTimes[ TOTAL_SOLDIERS ];
|
||||||
|
|
||||||
|
TAUNT_VALUES zApplicableTaunts[NUM_TAUNT];
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
void CopyNumEntriesIntoQuoteStruct( ) // Not used
|
void CopyNumEntriesIntoQuoteStruct( ) // Not used
|
||||||
{
|
{
|
||||||
@@ -1029,11 +1036,15 @@ BOOLEAN SaveCivQuotesToSaveGameFile( HWFILE hFile )
|
|||||||
return( TRUE );
|
return( TRUE );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// anv: used now
|
||||||
//is allowed remove. Not used and remove from SaveLoadGame.cpp.
|
//is allowed remove. Not used and remove from SaveLoadGame.cpp.
|
||||||
BOOLEAN LoadCivQuotesFromLoadGameFile( HWFILE hFile )
|
BOOLEAN LoadCivQuotesFromLoadGameFile( HWFILE hFile )
|
||||||
{
|
{
|
||||||
UINT32 uiNumBytesRead;
|
UINT32 uiNumBytesRead;
|
||||||
|
|
||||||
|
// anv: reset uiTauntFinishTimes after game is loaded (so enemies can taunt after guiBaseJA2Clock is decreased)
|
||||||
|
memset( &uiTauntFinishTimes, 0, sizeof( uiTauntFinishTimes ) );
|
||||||
|
|
||||||
FileRead( hFile, &gCivQuotes, sizeof( gCivQuotes ), &uiNumBytesRead );
|
FileRead( hFile, &gCivQuotes, sizeof( gCivQuotes ), &uiNumBytesRead );
|
||||||
if( uiNumBytesRead != sizeof( gCivQuotes ) )
|
if( uiNumBytesRead != sizeof( gCivQuotes ) )
|
||||||
{
|
{
|
||||||
@@ -1062,6 +1073,12 @@ void PossiblyStartEnemyTaunt( SOLDIERTYPE *pCiv, TAUNTTYPE iTauntType, SOLDIERTY
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// is enemy blocked from taunting at the moment?
|
||||||
|
if( uiTauntFinishTimes[pCiv->ubID] > GetJA2Clock() )
|
||||||
|
{
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
// check if generated person
|
// check if generated person
|
||||||
if ( !(IS_MERC_BODY_TYPE( pCiv )) || !(pCiv->ubProfile == NO_PROFILE) )
|
if ( !(IS_MERC_BODY_TYPE( pCiv )) || !(pCiv->ubProfile == NO_PROFILE) )
|
||||||
{
|
{
|
||||||
@@ -1079,7 +1096,7 @@ void PossiblyStartEnemyTaunt( SOLDIERTYPE *pCiv, TAUNTTYPE iTauntType, SOLDIERTY
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// only enemies that are able to speak at the moment can taunt
|
// only enemies that are able to speak at the moment can taunt
|
||||||
if ( pCiv->stats.bLife < OKLIFE || pCiv->bCollapsed )
|
if ( pCiv->stats.bLife < OKLIFE || pCiv->bBreathCollapsed )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1248,13 +1265,9 @@ void PossiblyStartEnemyTaunt( SOLDIERTYPE *pCiv, TAUNTTYPE iTauntType, SOLDIERTY
|
|||||||
// SANDRO - soldier taunts
|
// SANDRO - soldier taunts
|
||||||
void StartEnemyTaunt( SOLDIERTYPE *pCiv, TAUNTTYPE iTauntType, SOLDIERTYPE *pTarget )
|
void StartEnemyTaunt( SOLDIERTYPE *pCiv, TAUNTTYPE iTauntType, SOLDIERTYPE *pTarget )
|
||||||
{
|
{
|
||||||
UINT16 iTauntNumber;
|
CHAR16 sTauntText[ 320 ];
|
||||||
CHAR16 sTauntText[320];
|
|
||||||
CHAR16 gzTauntQuote[ 320 ];
|
CHAR16 gzTauntQuote[ 320 ];
|
||||||
TAUNT_VALUES zApplicableTaunts[1024];
|
|
||||||
UINT16 iApplicableTaunts = 0;
|
UINT16 iApplicableTaunts = 0;
|
||||||
BOOLEAN fApplicableAttitude[6];
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_ZOMBIES
|
#ifdef ENABLE_ZOMBIES
|
||||||
// Flugente: zombies don't talk
|
// Flugente: zombies don't talk
|
||||||
@@ -1262,11 +1275,12 @@ void StartEnemyTaunt( SOLDIERTYPE *pCiv, TAUNTTYPE iTauntType, SOLDIERTYPE *pTar
|
|||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// gCivQuoteData.bActive is checked in ShowTauntPopupBox() instead, taunt can be shown in log though!
|
||||||
// if we have a different quote on, return, this one is not important
|
// if we have a different quote on, return, this one is not important
|
||||||
if ( gCivQuoteData.bActive )
|
//if ( gCivQuoteData.bActive )
|
||||||
{
|
//{
|
||||||
return;
|
// return;
|
||||||
}
|
//}
|
||||||
|
|
||||||
// anv: check all taunts, and remember those applicable
|
// anv: check all taunts, and remember those applicable
|
||||||
for(UINT16 i=0; i<num_found_taunt; i++)
|
for(UINT16 i=0; i<num_found_taunt; i++)
|
||||||
@@ -1877,43 +1891,57 @@ void StartEnemyTaunt( SOLDIERTYPE *pCiv, TAUNTTYPE iTauntType, SOLDIERTYPE *pTar
|
|||||||
// everything ok, current taunt is applicable, remember it
|
// everything ok, current taunt is applicable, remember it
|
||||||
zApplicableTaunts[iApplicableTaunts] = zTaunt[i];
|
zApplicableTaunts[iApplicableTaunts] = zTaunt[i];
|
||||||
iApplicableTaunts++;
|
iApplicableTaunts++;
|
||||||
|
if(iApplicableTaunts >= MAX_APPLICABLE_TAUNTS)
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
// are there any applicable taunts?
|
// are there any applicable taunts?
|
||||||
if( iApplicableTaunts > 0 )
|
if( iApplicableTaunts > 0 )
|
||||||
{
|
{
|
||||||
// use random one
|
// use random one
|
||||||
swprintf( sTauntText, zApplicableTaunts[ Random(iApplicableTaunts) ].szText );
|
// use censored version if setting is set
|
||||||
|
UINT16 iChosenTaunt = Random(iApplicableTaunts);
|
||||||
|
if( gTauntsSettings.fTauntCensoredMode == TRUE && zApplicableTaunts[ iChosenTaunt ].szCensoredText[0] != 0 )
|
||||||
|
{
|
||||||
|
swprintf( sTauntText, zApplicableTaunts[ iChosenTaunt ].szCensoredText );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
swprintf( sTauntText, zApplicableTaunts[ iChosenTaunt ].szText );
|
||||||
|
}
|
||||||
|
#ifdef TAIWANESE
|
||||||
|
swprintf( gzTauntQuote, L"%s", sTauntText );
|
||||||
|
#else
|
||||||
|
swprintf( gzTauntQuote, L"\"%s\"", sTauntText );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// block this enemy from taunting for a time being
|
||||||
|
uiTauntFinishTimes[pCiv->ubID] = GetJA2Clock() + min( gTauntsSettings.sMaxDelay , max( gTauntsSettings.sMinDelay, FindDelayForString( gzTauntQuote ) + gTauntsSettings.sModDelay ) );
|
||||||
|
|
||||||
|
if( gTauntsSettings.fTauntMakeNoise == TRUE )
|
||||||
|
MakeNoise( pCiv->ubID, pCiv->sGridNo, pCiv->pathing.bLevel, pCiv->bOverTerrainType, gTauntsSettings.sVolume, NOISE_VOICE, gzTauntQuote );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(gTauntsSettings.fTauntShowPopupBox == TRUE)
|
||||||
|
{
|
||||||
|
if( gbPublicOpplist[gbPlayerNum][pCiv->ubID] == SEEN_CURRENTLY || gTauntsSettings.fTauntAlwaysShowPopupBox == TRUE )
|
||||||
|
{
|
||||||
|
ShowTauntPopupBox( pCiv, gzTauntQuote );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(gTauntsSettings.fTauntShowInLog == TRUE)
|
||||||
|
{
|
||||||
|
if( gbPublicOpplist[gbPlayerNum][pCiv->ubID] == SEEN_CURRENTLY || gTauntsSettings.fTauntAlwaysShowInLog == TRUE )
|
||||||
|
{
|
||||||
|
ScreenMsg( FONT_GRAY2, MSG_INTERFACE, L"%s: %s", pCiv->GetName(), gzTauntQuote );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TAIWANESE
|
|
||||||
swprintf( gzTauntQuote, L"%s", sTauntText );
|
|
||||||
#else
|
|
||||||
swprintf( gzTauntQuote, L"\"%s\"", sTauntText );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if( gTauntsSettings.fTauntMakeNoise == TRUE )
|
|
||||||
MakeNoise( pCiv->ubID, pCiv->sGridNo, pCiv->pathing.bLevel, pCiv->bOverTerrainType, gTauntsSettings.sVolume, NOISE_VOICE, gzTauntQuote );
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(gTauntsSettings.fTauntShowPopupBox == TRUE)
|
|
||||||
{
|
|
||||||
if( gbPublicOpplist[gbPlayerNum][pCiv->ubID] == SEEN_CURRENTLY || gTauntsSettings.fTauntAlwaysShowPopupBox == TRUE )
|
|
||||||
{
|
|
||||||
ShowTauntPopupBox( pCiv, gzTauntQuote );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(gTauntsSettings.fTauntShowInLog == TRUE)
|
|
||||||
{
|
|
||||||
if( gbPublicOpplist[gbPlayerNum][pCiv->ubID] == SEEN_CURRENTLY || gTauntsSettings.fTauntAlwaysShowInLog == TRUE )
|
|
||||||
{
|
|
||||||
ScreenMsg( FONT_GRAY2, MSG_INTERFACE, L"%s: %s", pCiv->GetName(), gzTauntQuote );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowTauntPopupBox( SOLDIERTYPE *pCiv, STR16 gzTauntQuote )
|
void ShowTauntPopupBox( SOLDIERTYPE *pCiv, STR16 gzTauntQuote )
|
||||||
@@ -1922,6 +1950,12 @@ void ShowTauntPopupBox( SOLDIERTYPE *pCiv, STR16 gzTauntQuote )
|
|||||||
INT16 sScreenX, sScreenY;
|
INT16 sScreenX, sScreenY;
|
||||||
VIDEO_OVERLAY_DESC VideoOverlayDesc;
|
VIDEO_OVERLAY_DESC VideoOverlayDesc;
|
||||||
|
|
||||||
|
// stop if other civ quote is already being shown
|
||||||
|
if( gCivQuoteData.bActive == TRUE )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Determine location...
|
// Determine location...
|
||||||
// Get location of civ on screen.....
|
// Get location of civ on screen.....
|
||||||
GetSoldierScreenPos( pCiv, &sScreenX, &sScreenY );
|
GetSoldierScreenPos( pCiv, &sScreenX, &sScreenY );
|
||||||
|
|||||||
@@ -267,6 +267,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
UINT16 uiIndex;
|
UINT16 uiIndex;
|
||||||
CHAR16 szText[320];
|
CHAR16 szText[320];
|
||||||
|
CHAR16 szCensoredText[320];
|
||||||
UINT64 uiFlags;
|
UINT64 uiFlags;
|
||||||
UINT64 uiFlags2;
|
UINT64 uiFlags2;
|
||||||
INT16 value[TAUNT_MAX];
|
INT16 value[TAUNT_MAX];
|
||||||
|
|||||||
+1
-1
@@ -238,7 +238,7 @@ typedef PARSE_STAGE;
|
|||||||
#define SQUADNAMEFILENAME "SquadNames.xml"
|
#define SQUADNAMEFILENAME "SquadNames.xml"
|
||||||
#define BACKGROUNDSFILENAME "Backgrounds.xml"
|
#define BACKGROUNDSFILENAME "Backgrounds.xml"
|
||||||
#define TAUNTSFILENAME "EnemyTaunts.xml"
|
#define TAUNTSFILENAME "EnemyTaunts.xml"
|
||||||
#define TAUNTSFILENAMEBEGINNING "EnemyTaunts"
|
#define TAUNTSFILENAMEBEGINNING "EnemyTaunts\\EnemyTaunts"
|
||||||
#define TAUNTSFILENAMEENDING ".xml"
|
#define TAUNTSFILENAMEENDING ".xml"
|
||||||
|
|
||||||
#define ENEMY_ADMIN_PROFILE_FILENAME "Profiles\\SoldierProfileEnemyAdmin.xml"
|
#define ENEMY_ADMIN_PROFILE_FILENAME "Profiles\\SoldierProfileEnemyAdmin.xml"
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ tauntStartElementHandle(void *userData, const XML_Char *name, const XML_Char **a
|
|||||||
else if(pData->curElement == ELEMENT &&
|
else if(pData->curElement == ELEMENT &&
|
||||||
(strcmp(name, "uiIndex") == 0 ||
|
(strcmp(name, "uiIndex") == 0 ||
|
||||||
strcmp(name, "szText") == 0 ||
|
strcmp(name, "szText") == 0 ||
|
||||||
|
strcmp(name, "szCensoredText") == 0 ||
|
||||||
|
|
||||||
strcmp(name, "aggressive") == 0 ||
|
strcmp(name, "aggressive") == 0 ||
|
||||||
strcmp(name, "defensive") == 0 ||
|
strcmp(name, "defensive") == 0 ||
|
||||||
@@ -233,6 +234,8 @@ tauntEndElementHandle(void *userData, const XML_Char *name)
|
|||||||
{
|
{
|
||||||
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curArray[pData->curTaunt.uiIndex].szText, sizeof(pData->curTaunt.szText)/sizeof(pData->curTaunt.szText[0]) );
|
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curArray[pData->curTaunt.uiIndex].szText, sizeof(pData->curTaunt.szText)/sizeof(pData->curTaunt.szText[0]) );
|
||||||
pData->curArray[pData->curTaunt.uiIndex].szText[sizeof(pData->curTaunt.szText)/sizeof(pData->curTaunt.szText[0]) - 1] = '\0';
|
pData->curArray[pData->curTaunt.uiIndex].szText[sizeof(pData->curTaunt.szText)/sizeof(pData->curTaunt.szText[0]) - 1] = '\0';
|
||||||
|
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curArray[pData->curTaunt.uiIndex].szCensoredText, sizeof(pData->curTaunt.szCensoredText)/sizeof(pData->curTaunt.szCensoredText[0]) );
|
||||||
|
pData->curArray[pData->curTaunt.uiIndex].szCensoredText[sizeof(pData->curTaunt.szCensoredText)/sizeof(pData->curTaunt.szCensoredText[0]) - 1] = '\0';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -297,6 +300,13 @@ tauntEndElementHandle(void *userData, const XML_Char *name)
|
|||||||
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curTaunt.szText, sizeof(pData->curTaunt.szText)/sizeof(pData->curTaunt.szText[0]) );
|
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curTaunt.szText, sizeof(pData->curTaunt.szText)/sizeof(pData->curTaunt.szText[0]) );
|
||||||
pData->curTaunt.szText[sizeof(pData->curTaunt.szText)/sizeof(pData->curTaunt.szText[0]) - 1] = '\0';
|
pData->curTaunt.szText[sizeof(pData->curTaunt.szText)/sizeof(pData->curTaunt.szText[0]) - 1] = '\0';
|
||||||
}
|
}
|
||||||
|
else if(strcmp(name, "szCensoredText") == 0 )
|
||||||
|
{
|
||||||
|
pData->curElement = ELEMENT;
|
||||||
|
|
||||||
|
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curTaunt.szCensoredText, sizeof(pData->curTaunt.szCensoredText)/sizeof(pData->curTaunt.szCensoredText[0]) );
|
||||||
|
pData->curTaunt.szCensoredText[sizeof(pData->curTaunt.szCensoredText)/sizeof(pData->curTaunt.szCensoredText[0]) - 1] = '\0';
|
||||||
|
}
|
||||||
else if(strcmp(name, "aggressive") == 0)
|
else if(strcmp(name, "aggressive") == 0)
|
||||||
{
|
{
|
||||||
pData->curElement = ELEMENT;
|
pData->curElement = ELEMENT;
|
||||||
|
|||||||
Reference in New Issue
Block a user