diff --git a/GameSettings.cpp b/GameSettings.cpp index afc10eb5..0fe21fd9 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -3500,6 +3500,9 @@ void LoadTauntsSettings() gTauntsSettings.fTauntShowInLogIfHeard = iniReader.ReadBoolean("Taunts Settings","TAUNT_SHOW_IN_LOG_IF_HEARD", TRUE ); gTauntsSettings.fTauntAlwaysShowPopupBox = iniReader.ReadBoolean("Taunts Settings","TAUNT_ALWAYS_SHOW_POPUP_BOX", FALSE ); gTauntsSettings.fTauntAlwaysShowInLog = iniReader.ReadBoolean("Taunts Settings","TAUNT_ALWAYS_SHOW_IN_LOG", FALSE ); + gTauntsSettings.fTauntVoice = iniReader.ReadBoolean("Taunts Settings", "TAUNT_VOICE", FALSE); + gTauntsSettings.fTauntVoiceShowInfo = iniReader.ReadBoolean("Taunts Settings", "TAUNT_VOICE_SHOW_INFO", FALSE); + gTauntsSettings.sVolume = iniReader.ReadInteger("Taunts Settings","TAUNT_VOLUME",30, 0, 65535 ); gTauntsSettings.sModDelay = iniReader.ReadInteger("Taunts Settings","TAUNT_MOD_DELAY",100, -32767, 32767 ); gTauntsSettings.sMinDelay = iniReader.ReadInteger("Taunts Settings","TAUNT_MIN_DELAY",500, 0, 65535 ); diff --git a/GameSettings.h b/GameSettings.h index 3ebfdaa1..9dac15af 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -1560,6 +1560,8 @@ typedef struct BOOLEAN fTauntShowInLogIfHeard; BOOLEAN fTauntAlwaysShowPopupBox; BOOLEAN fTauntAlwaysShowInLog; + BOOLEAN fTauntVoice; + BOOLEAN fTauntVoiceShowInfo; UINT16 sVolume; INT16 sModDelay; UINT16 sMinDelay; diff --git a/Tactical/Civ Quotes.cpp b/Tactical/Civ Quotes.cpp index c3e1272b..649524aa 100644 --- a/Tactical/Civ Quotes.cpp +++ b/Tactical/Civ Quotes.cpp @@ -39,6 +39,7 @@ #include "Soldier Profile.h" #include "Campaign.h" #include "opplist.h" +#include "Sound Control.h" // sevenfm: voice taunts #define DIALOGUE_DEFAULT_WIDTH 200 #define EXTREAMLY_LOW_TOWN_LOYALTY 20 @@ -1151,7 +1152,6 @@ void PossiblyStartEnemyTaunt( SOLDIERTYPE *pCiv, TAUNTTYPE iTauntType, UINT32 ui // is enemy blocked from taunting at the moment? if( uiTauntFinishTimes[pCiv->ubID] > GetJA2Clock() ) { - return; } // check if generated person @@ -1160,10 +1160,18 @@ void PossiblyStartEnemyTaunt( SOLDIERTYPE *pCiv, TAUNTTYPE iTauntType, UINT32 ui return; } // only enemies and militia taunt - if ( pCiv->bTeam != ENEMY_TEAM && pCiv->bTeam != MILITIA_TEAM ) + // sevenfm: allow voice taunts for hostile civilians with group + if (pCiv->bTeam != ENEMY_TEAM && + pCiv->bTeam != MILITIA_TEAM && + !(pCiv->bTeam == CIV_TEAM && pCiv->ubCivilianGroup != NON_CIV_GROUP && !pCiv->aiData.bNeutral && gTauntsSettings.fTauntVoice)) { return; } + /*if ( pCiv->bTeam != ENEMY_TEAM && pCiv->bTeam != MILITIA_TEAM ) + { + return; + }*/ + // only visible enemies taunt (unless set otherwise) if ( ( pCiv->bVisible == -1 ) && ( gTauntsSettings.fTauntOnlyVisibleEnemies == TRUE ) ) { @@ -1346,12 +1354,15 @@ void StartEnemyTaunt( SOLDIERTYPE *pCiv, TAUNTTYPE iTauntType, SOLDIERTYPE *pTar if ( pCiv->IsZombie() ) return; - // 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 ( gCivQuoteData.bActive ) - //{ - // return; - //} + // sevenfm: play audio taunt if possible + if (gTauntsSettings.fTauntVoice) + { + // try to play voice taunt, use noise if gTauntsSettings.fTauntMakeNoise is TRUE + PlayVoiceTaunt(pCiv, iTauntType, pTarget); + // block this enemy from taunting for a time being + uiTauntFinishTimes[pCiv->ubID] = GetJA2Clock() + min(gTauntsSettings.sMaxDelay, max(gTauntsSettings.sMinDelay, FindDelayForString(L"You're the disease and I'm the cure!") + gTauntsSettings.sModDelay)); + return; + } // anv: check all taunts, and remember those applicable for(UINT16 i=0; iubID] = 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 ); + MakeNoise( pCiv->ubID, pCiv->sGridNo, pCiv->pathing.bLevel, pCiv->bOverTerrainType, (UINT8)gTauntsSettings.sVolume, NOISE_VOICE, gzTauntQuote ); else { if(gTauntsSettings.fTauntShowPopupBox == TRUE) @@ -2099,3 +2110,281 @@ BOOLEAN CivQuoteActive() { return gCivQuoteData.bActive; } + +STR VoiceTauntFileName[] = +{ + "FIRE_GUN", + "FIRE_LAUNCHER", + "ATTACK_BLADE", + "ATTACK_HTH", + + "THROW_KNIFE", + "THROW_GRENADE", + + "OUT_OF_AMMO", + "RELOAD", + + "STEAL", + + // AI routines + "CHARGE_BLADE", + "CHARGE_HTH", + "RUN_AWAY", + "SEEK_NOISE", + "ALERT", + "SUSPICIOUS", + "NOTICED_UNSEEN", + "SAY_HI", + "INFORM_ABOUT", + + // got_hit_xxx + "GOT_HIT", + "GOT_HIT_GUNFIRE", + "GOT_HIT_BLADE", + "GOT_HIT_HTH", + "GOT_HIT_FALLROOF", + "GOT_HIT_BLOODLOSS", + "GOT_HIT_EXPLOSION", + "GOT_HIT_GAS", + "GOT_HIT_TENTACLES", + "GOT_HIT_STRUCTURE_EXPLOSION", + "GOT_HIT_OBJECT", + "GOT_HIT_THROWING_KNIFE", + + "GOT_DEAFENED", + "GOT_BLINDED", + + "GOT_ROBBED", + + // got_missed_xxx + "GOT_MISSED", + "GOT_MISSED_GUNFIRE", + "GOT_MISSED_BLADE", + "GOT_MISSED_HTH", + "GOT_MISSED_THROWING_KNIFE", + + // hit_xxx + "HIT", + "HIT_GUNFIRE", + "HIT_BLADE", + "HIT_HTH", + "HIT_EXPLOSION", + "HIT_THROWING_KNIFE", + + // kill_xxx + "KILL", + "KILL_GUNFIRE", + "KILL_BLADE", + "KILL_HTH", + "KILL_THROWING_KNIFE", + "HEAD_POP", + + // miss_xxx + "MISS", + "MISS_GUNFIRE", + "TAUNT_MISS_BLADE", + "MISS_HTH", + "MISS_THROWING_KNIFE", + + // ripostes to merc quotes + "RIPOSTE" +}; + +// sevenfm: voice taunts +BOOLEAN PlayVoiceTaunt(SOLDIERTYPE *pCiv, TAUNTTYPE iTauntType, SOLDIERTYPE *pTarget) +{ + CHAR8 filename[1024]; + CHAR8 filenameExtra[1024]; + CHAR16 noise[1024]; + CHAR8 buf[1024]; + INT32 iRandomTaunt = 0; + UINT8 ubExtraTaunts = 0; + + CHECKF(pCiv); + + if (!gTauntsSettings.fTauntVoice) + { + return FALSE; + } + + // show some information about taunts + if (gTauntsSettings.fTauntVoiceShowInfo) + ScreenMsg(FONT_MCOLOR_LTGREEN, MSG_INTERFACE, L"Soldier [%d] TauntType %d", pCiv->ubID, iTauntType); + + // cannot taunt when dead or collapsed + if (pCiv->stats.bLife < OKLIFE || pCiv->bCollapsed || pCiv->bBreathCollapsed) + { + if (gTauntsSettings.fTauntVoiceShowInfo) + ScreenMsg(FONT_MCOLOR_LTGREEN, MSG_INTERFACE, L"Bad soldier state (dying or collapsed)"); + + return FALSE; + } + + if (iTauntType < TAUNT_FIRE_GUN || iTauntType > TAUNT_RIPOSTE) + { + if (gTauntsSettings.fTauntVoiceShowInfo) + ScreenMsg(FONT_MCOLOR_LTGREEN, MSG_INTERFACE, L"Bad taunt"); + + return FALSE; + } + + strcpy(filename, "VoiceTaunts"); + + // prepare team + if (pCiv->bTeam == ENEMY_TEAM) + { + strcat(filename, "\\Army\\"); + } + else if (pCiv->bTeam == MILITIA_TEAM) + { + strcat(filename, "\\Militia\\"); + } + else if (pCiv->bTeam == CIV_TEAM && pCiv->ubCivilianGroup != NON_CIV_GROUP) + { + sprintf(buf, "\\Civgroup%02d\\", pCiv->ubCivilianGroup); + strcat(filename, buf); + } + else + { + if (gTauntsSettings.fTauntVoiceShowInfo) + ScreenMsg(FONT_MCOLOR_LTGREEN, MSG_INTERFACE, L"Bad soldier team"); + + return FALSE; + } + + // prepare gender + if (pCiv->ubBodyType <= STOCKYMALE) + { + strcat(filename, "Male\\"); + } + else if (pCiv->ubBodyType == REGFEMALE) + { + strcat(filename, "Female\\"); + } + else + { + if (gTauntsSettings.fTauntVoiceShowInfo) + ScreenMsg(FONT_MCOLOR_LTGREEN, MSG_INTERFACE, L"Incorrect bodytype"); + + return FALSE; + } + + // count possible voices + UINT8 ubVoiceCount; + for (ubVoiceCount = 1; ubVoiceCount <= 100; ubVoiceCount++) + { + sprintf(buf, "%s%02d", filename, ubVoiceCount); + strcat(buf, "\\alert.ogg"); + + // check that folder exists + if (!FileExists(buf)) + { + if (gTauntsSettings.fTauntVoiceShowInfo) + { + mbstowcs(noise, buf, strlen(buf) + 1); + ScreenMsg(FONT_GREEN, MSG_INTERFACE, noise); + } + + break; + } + } + // find last good number + ubVoiceCount--; + + if (ubVoiceCount < 1) + { + if (gTauntsSettings.fTauntVoiceShowInfo) + ScreenMsg(FONT_MCOLOR_LTGREEN, MSG_INTERFACE, L"Could not find any voice folder"); + + return FALSE; + } + + if (gTauntsSettings.fTauntVoiceShowInfo) + ScreenMsg(FONT_MCOLOR_LTGREEN, MSG_INTERFACE, L"found %d voices", ubVoiceCount); + + // prepare voice folder name + sprintf(buf, "%02d", 1 + pCiv->ubID % ubVoiceCount); + strcat(filename, buf); + strcat(filename, "\\"); + + // prepare base taunt filename + strcat(filename, VoiceTauntFileName[iTauntType]); + + // count possible extra filenames + ubExtraTaunts = 0; + for (UINT8 ubCheck = 1; ubCheck <= 10; ubCheck++) + { + // check extra taunt file + strcpy(filenameExtra, filename); + sprintf(buf, " %d", ubExtraTaunts); + strcat(filenameExtra, buf); + strcat(filenameExtra, ".ogg"); + if (!FileExists(filenameExtra)) + { + break; + } + ubExtraTaunts = ubCheck; + } + + // possibly use extra taunt + iRandomTaunt = Random(ubExtraTaunts + 1); + if (iRandomTaunt > 0) + { + sprintf(buf, " %d", iRandomTaunt); + strcat(filename, buf); + } + + strcat(filename, ".ogg"); + + // log taunt file names + if (gTauntsSettings.fTauntVoiceShowInfo) + { + FILE *OutFile; + if ((OutFile = fopen("VoiceTauntLog.txt", "a+t")) != NULL) + { + fprintf(OutFile, "Soldier [%d] TauntType %d %s\n", + pCiv->ubID, + iTauntType, + filename); + fclose(OutFile); + } + + // show some information about taunts + mbstowcs(noise, filename, strlen(filename) + 1); + ScreenMsg(FONT_GREEN, MSG_INTERFACE, noise); + } + + // check that taunt file exists + if (!FileExists(filename)) + { + if (gTauntsSettings.fTauntVoiceShowInfo) + { + mbstowcs(noise, filename, strlen(filename) + 1); + ScreenMsg(FONT_GREEN, MSG_INTERFACE, noise); + ScreenMsg(FONT_MCOLOR_LTRED, MSG_INTERFACE, L"Taunt: no file %s", noise); + } + + return FALSE; + } + + if (gTauntsSettings.fTauntMakeNoise == TRUE) + { + // convert char to char16 + mbstowcs(noise, filename, strlen(filename) + 1); + // use filename as taunt text, play sound later + MakeNoise(pCiv->ubID, pCiv->sGridNo, pCiv->pathing.bLevel, pCiv->bOverTerrainType, (UINT8)gTauntsSettings.sVolume, NOISE_VOICE, noise); + } + else + { + // play voice taunt + if (PlayJA2SampleFromFile(filename, RATE_11025, SoundVolume(HIGHVOLUME, pCiv->sGridNo), 1, SoundDir(pCiv->sGridNo)) == SOUND_ERROR) + { + if (gTauntsSettings.fTauntVoiceShowInfo) + ScreenMsg(FONT_MCOLOR_LTRED, MSG_INTERFACE, L"Failed to play taunt"); + + return FALSE; + } + } + + return TRUE; +} \ No newline at end of file diff --git a/Tactical/Civ Quotes.h b/Tactical/Civ Quotes.h index d950b9be..0c466651 100644 --- a/Tactical/Civ Quotes.h +++ b/Tactical/Civ Quotes.h @@ -158,6 +158,9 @@ void PossiblyStartEnemyTaunt( SOLDIERTYPE *pCiv, TAUNTTYPE iTauntType, UINT32 ui void StartEnemyTaunt( SOLDIERTYPE *pCiv, TAUNTTYPE iTauntType, SOLDIERTYPE *pTarget = NULL ); //enemy taunts - SANDRO // anv: added pTarget argument void ShowTauntPopupBox( SOLDIERTYPE *pCiv, STR16 gzTauntQuote ); +// sevenfm: voice taunts +BOOLEAN PlayVoiceTaunt(SOLDIERTYPE *pCiv, TAUNTTYPE iTauntType, SOLDIERTYPE *pTarget); + void InitCivQuoteSystem( ); void StartCivQuote( SOLDIERTYPE *pCiv ); diff --git a/Tactical/LOS.cpp b/Tactical/LOS.cpp index 42c88ded..003b3d89 100644 --- a/Tactical/LOS.cpp +++ b/Tactical/LOS.cpp @@ -4949,7 +4949,7 @@ INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, ddVerticAngle += ddAdjustedVerticAngle; //Logging for debugging - //#ifdef JA2TESTVERSION + #ifdef JA2TESTVERSION if(!fFake) { FILE *OutFile; @@ -4968,7 +4968,7 @@ INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, fclose(OutFile); } } - //#endif + #endif } //Just calculate the increments the bullet will use, not any of the to-hit adjustments, because we already did. diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index 15f6a61d..c834a025 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -10342,7 +10342,7 @@ INT8 CheckStatusNearbyFriendlies( SOLDIERTYPE *pSoldier ) } } // Incapacitated or heavily suppressed friends will not be good for our tolerance! - else if ( (pLeader->aiData.bShock > pSoldier->aiData.bShock || pLeader->stats.bLife <= OKLIFE) ) + else if ( (pLeader->aiData.bShock > pSoldier->aiData.bShock || pLeader->stats.bLife < OKLIFE) ) { usEffectiveRangeToLeader = PythSpacesAway( pSoldier->sGridNo, pLeader->sGridNo ); // If they are no more than 5 tiles away, diff --git a/Tactical/Weapons.cpp b/Tactical/Weapons.cpp index ef3c2ee2..4ef71697 100644 --- a/Tactical/Weapons.cpp +++ b/Tactical/Weapons.cpp @@ -5320,14 +5320,28 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN { if( Item[ pBullet->pFirer->usAttackingWeapon ].usItemClass & IC_GUN ) { - if( MercPtrs[ pBullet->pFirer->ubOppNum ]->aiData.bOppList[ pBullet->pFirer->ubID ] == SEEN_CURRENTLY ) - PossiblyStartEnemyTaunt( MercPtrs[ pBullet->pFirer->ubOppNum ], TAUNT_GOT_MISSED_GUNFIRE, pBullet->pFirer->ubID ); + if (gTauntsSettings.fTauntVoice) + { + // say taunt only to inform others + if (gbPublicOpplist[MercPtrs[pBullet->pFirer->ubOppNum]->bTeam][pBullet->pFirer->ubID] != SEEN_CURRENTLY && + gbPublicOpplist[MercPtrs[pBullet->pFirer->ubOppNum]->bTeam][pBullet->pFirer->ubID] != SEEN_THIS_TURN && + gTacticalStatus.Team[MercPtrs[pBullet->pFirer->ubOppNum]->bTeam].bMenInSector > 1) + { + PossiblyStartEnemyTaunt(MercPtrs[pBullet->pFirer->ubOppNum], TAUNT_GOT_MISSED_GUNFIRE, pBullet->pFirer->ubID); + } + } + else if (MercPtrs[pBullet->pFirer->ubOppNum]->aiData.bOppList[pBullet->pFirer->ubID] == SEEN_CURRENTLY) + { + PossiblyStartEnemyTaunt(MercPtrs[pBullet->pFirer->ubOppNum], TAUNT_GOT_MISSED_GUNFIRE, pBullet->pFirer->ubID); + } + PossiblyStartEnemyTaunt( pBullet->pFirer, TAUNT_MISS_GUNFIRE, pBullet->pFirer->ubOppNum ); } else if( Item[ pBullet->pFirer->usAttackingWeapon ].usItemClass & IC_THROWING_KNIFE ) { if( MercPtrs[ pBullet->pFirer->ubOppNum ]->aiData.bOppList[ pBullet->pFirer->ubID ] == SEEN_CURRENTLY ) PossiblyStartEnemyTaunt( MercPtrs[ pBullet->pFirer->ubOppNum ], TAUNT_GOT_MISSED_THROWING_KNIFE, pBullet->pFirer->ubID ); + PossiblyStartEnemyTaunt( pBullet->pFirer, TAUNT_MISS_THROWING_KNIFE, pBullet->pFirer->ubOppNum ); } } diff --git a/Tactical/opplist.cpp b/Tactical/opplist.cpp index a7436893..0568357b 100644 --- a/Tactical/opplist.cpp +++ b/Tactical/opplist.cpp @@ -6007,7 +6007,9 @@ void ProcessNoise(UINT8 ubNoiseMaker, INT32 sGridNo, INT8 bLevel, UINT8 ubTerrTy break; case MILITIA_TEAM: // if the noisemaker is militia and still on our side, ignore noise if we're listening - if ( pSoldier->bTeam == OUR_TEAM && MercPtrs[ ubNoiseMaker ]->bSide == 0 ) + // sevenfm: allow taunts from militia + if (pSoldier->bTeam == OUR_TEAM && MercPtrs[ubNoiseMaker]->bSide == 0 && (ubNoiseType != NOISE_VOICE || !gTauntsSettings.fTauntVoice)) + //if ( pSoldier->bTeam == OUR_TEAM && MercPtrs[ ubNoiseMaker ]->bSide == 0 ) { continue; } @@ -6740,43 +6742,66 @@ void TellPlayerAboutNoise( SOLDIERTYPE *pSoldier, UINT8 ubNoiseMaker, INT32 sGri } // anv: special treatment of NOISE_VOICE - also display taunt message - if( ubNoiseType == NOISE_VOICE ) + if (ubNoiseType == NOISE_VOICE && ubNoiseMaker != NOBODY) { // information about direction etc. only displayed if we don't see noise maker - if( gbPublicOpplist[gbPlayerNum][ubNoiseMaker] != SEEN_CURRENTLY && pSoldier->aiData.bOppList[ubNoiseMaker] != SEEN_CURRENTLY ) + // sevenfm: don't show noise messages from militia (if on our side) + if (gbPublicOpplist[gbPlayerNum][ubNoiseMaker] != SEEN_CURRENTLY && pSoldier->aiData.bOppList[ubNoiseMaker] != SEEN_CURRENTLY && + !(MercPtrs[ubNoiseMaker]->bTeam == MILITIA_TEAM && MercPtrs[ubNoiseMaker]->bSide == 0)) + //if( gbPublicOpplist[gbPlayerNum][ubNoiseMaker] != SEEN_CURRENTLY && pSoldier->aiData.bOppList[ubNoiseMaker] != SEEN_CURRENTLY ) { - if( bLevel == pSoldier->pathing.bLevel && ubNoiseType == NOISE_VOICE ) + if (bLevel == pSoldier->pathing.bLevel) { - ScreenMsg( MSG_FONT_YELLOW, MSG_INTERFACE, pNewNoiseStr[ubNoiseType], pSoldier->name, pNoiseVolStr[ubVolumeIndex], pDirectionStr[ubNoiseDir] ); + ScreenMsg(MSG_FONT_YELLOW, MSG_INTERFACE, pNewNoiseStr[ubNoiseType], pSoldier->name, pNoiseVolStr[ubVolumeIndex], pDirectionStr[ubNoiseDir]); } - else if ( bLevel > pSoldier->pathing.bLevel ) + else if (bLevel > pSoldier->pathing.bLevel) { // from above! - ScreenMsg( MSG_FONT_YELLOW, MSG_INTERFACE, pNewNoiseStr[ubNoiseType], pSoldier->name, pNoiseVolStr[ubVolumeIndex], gzLateLocalizedString[6] ); + ScreenMsg(MSG_FONT_YELLOW, MSG_INTERFACE, pNewNoiseStr[ubNoiseType], pSoldier->name, pNoiseVolStr[ubVolumeIndex], gzLateLocalizedString[6]); } else { // from below! - ScreenMsg( MSG_FONT_YELLOW, MSG_INTERFACE, pNewNoiseStr[ubNoiseType], pSoldier->name, pNoiseVolStr[ubVolumeIndex], gzLateLocalizedString[7] ); + ScreenMsg(MSG_FONT_YELLOW, MSG_INTERFACE, pNewNoiseStr[ubNoiseType], pSoldier->name, pNoiseVolStr[ubVolumeIndex], gzLateLocalizedString[7]); } } + if( ubVolumeIndex > 0 ) // definite noise - we're able to recognize words { - // do we know who said that? - if( gbPublicOpplist[gbPlayerNum][ubNoiseMaker] == SEEN_CURRENTLY || pSoldier->aiData.bOppList[ubNoiseMaker] == SEEN_CURRENTLY ) + CHAR8 filename[1024]; + + if (gTauntsSettings.fTauntVoiceShowInfo) + ScreenMsg(FONT_ORANGE, MSG_INTERFACE, zNoiseMessage); + + // convert wchar to char + wcstombs(filename, zNoiseMessage, wcslen(zNoiseMessage) + 1); + // sevenfm: play voice taunt (check that noise string is a filename) + if (gTauntsSettings.fTauntVoice && + strlen(filename) != 0 && + strstr(filename, "VoiceTaunts\\") != NULL) { - if( gTauntsSettings.fTauntShowPopupBox == TRUE ) - ShowTauntPopupBox( MercPtrs[ubNoiseMaker], zNoiseMessage ); - if( gTauntsSettings.fTauntShowInLog == TRUE ) - ScreenMsg( FONT_GRAY2, MSG_INTERFACE, L"%s: %s", MercPtrs[ubNoiseMaker]->GetName(), zNoiseMessage ); + UINT32 playResult = PlayJA2SampleFromFile(filename, RATE_11025, SoundVolume(HIGHVOLUME, pSoldier->sGridNo), 1, SoundDir(pSoldier->sGridNo)); + if (playResult == SOUND_ERROR && gTauntsSettings.fTauntVoiceShowInfo) + ScreenMsg(FONT_MCOLOR_LTRED, MSG_INTERFACE, L"Noise: Failed to play taunt"); } else { - if( gTauntsSettings.fTauntShowPopupBox == TRUE && gTauntsSettings.fTauntShowPopupBoxIfHeard == TRUE ) - ShowTauntPopupBox( MercPtrs[ubNoiseMaker], zNoiseMessage ); - if( gTauntsSettings.fTauntShowInLog == TRUE && gTauntsSettings.fTauntShowInLogIfHeard == TRUE ) - ScreenMsg( FONT_GRAY2, MSG_INTERFACE, L"%s: %s", pTauntUnknownVoice[0], zNoiseMessage ); - } + // do we know who said that? + if (gbPublicOpplist[gbPlayerNum][ubNoiseMaker] == SEEN_CURRENTLY || pSoldier->aiData.bOppList[ubNoiseMaker] == SEEN_CURRENTLY) + { + if (gTauntsSettings.fTauntShowPopupBox == TRUE) + ShowTauntPopupBox(MercPtrs[ubNoiseMaker], zNoiseMessage); + if (gTauntsSettings.fTauntShowInLog == TRUE) + ScreenMsg(FONT_GRAY2, MSG_INTERFACE, L"%s: %s", MercPtrs[ubNoiseMaker]->GetName(), zNoiseMessage); + } + else + { + if (gTauntsSettings.fTauntShowPopupBox == TRUE && gTauntsSettings.fTauntShowPopupBoxIfHeard == TRUE) + ShowTauntPopupBox(MercPtrs[ubNoiseMaker], zNoiseMessage); + if (gTauntsSettings.fTauntShowInLog == TRUE && gTauntsSettings.fTauntShowInLogIfHeard == TRUE) + ScreenMsg(FONT_GRAY2, MSG_INTERFACE, L"%s: %s", pTauntUnknownVoice[0], zNoiseMessage); + } + } } } else if ( bLevel == pSoldier->pathing.bLevel || ubNoiseType == NOISE_EXPLOSION || ubNoiseType == NOISE_SCREAM || ubNoiseType == NOISE_ROCK_IMPACT || ubNoiseType == NOISE_GRENADE_IMPACT ) @@ -6817,20 +6842,14 @@ void TellPlayerAboutNoise( SOLDIERTYPE *pSoldier, UINT8 ubNoiseMaker, INT32 sGri //DIGICRAB: Loud Sound Locator - //show a locator for very loud noises if we are in PLATINUM mode and have an extended ear - //Madd: if(gGameOptions.ubGameStyle == STYLE_PLATINUM && ubVolumeIndex >= 2) + //show a locator for very loud noises if we have an extended ear if(ubVolumeIndex >= 2) { -// INT8 bSlot; - - //bSlot = FindObj( pSoldier, EXTENDEDEAR ); - //if ( bSlot == HEAD1POS || bSlot == HEAD2POS) if ( FindHearingAid(pSoldier) ) BeginMultiPurposeLocator(sGridNo, bLevel, (INT8)((gTacticalStatus.uiFlags & TURNBASED) && ( gTacticalStatus.uiFlags & INCOMBAT ))); } // flag soldier as having reported noise in a particular direction - } void VerifyAndDecayOpplist(SOLDIERTYPE *pSoldier)