You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1203 lines
36 KiB
1203 lines
36 KiB
#include "cbase.h" |
|
#include "asw_marine_speech.h" |
|
#include "asw_marine.h" |
|
#include "asw_marine_resource.h" |
|
#include "asw_gamerules.h" |
|
#include "engine/IEngineSound.h" |
|
#include "SoundEmitterSystem/isoundemittersystembase.h" |
|
#include "soundchars.h" |
|
#include "ndebugoverlay.h" |
|
#include "asw_game_resource.h" |
|
#include "te_effect_dispatch.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
extern ISoundEmitterSystemBase *soundemitterbase; |
|
|
|
// chatter probabilites (1/x) |
|
#define BASE_CHATTER_SELECTION_CHANCE 5.0f |
|
#define CHATTER_INTERVAL 3.0f |
|
#define ASW_INTERVAL_CHATTER_INCOMING 30.0f |
|
#define ASW_INTERVAL_CHATTER_NO_AMMO 30.0f |
|
#define ASW_INTERVAL_FF 12.0f |
|
|
|
#define ASW_CALM_CHATTER_TIME 10.0f |
|
|
|
// chance of doing a direction hold position shout (from 0 to 1) |
|
#define ASW_DIRECTIONAL_HOLDING_CHATTER 0.5f |
|
|
|
ConVar asw_debug_marine_chatter("asw_debug_marine_chatter", "0", 0, "Show debug info about when marine chatter is triggered"); |
|
|
|
#define ACTOR_SARGE (1 << 0) |
|
#define ACTOR_WILDCAT (1 << 1) |
|
#define ACTOR_FAITH (1 << 2) |
|
#define ACTOR_CRASH (1 << 3) |
|
#define ACTOR_JAEGER (1 << 4) |
|
#define ACTOR_WOLFE (1 << 5) |
|
#define ACTOR_BASTILLE (1 << 6) |
|
#define ACTOR_VEGAS (1 << 7) |
|
#define ACTOR_FLYNN (1 << 8) |
|
#define ACTOR_ALL (ACTOR_SARGE | ACTOR_JAEGER | ACTOR_WILDCAT | ACTOR_WOLFE | ACTOR_FAITH | ACTOR_BASTILLE | ACTOR_CRASH | ACTOR_FLYNN) |
|
|
|
int CASW_MarineSpeech::s_CurrentConversation = CONV_NONE; |
|
int CASW_MarineSpeech::s_CurrentConversationChatterStage = -1; |
|
int CASW_MarineSpeech::s_iCurrentConvLine = -1; |
|
CHandle<CASW_Marine> CASW_MarineSpeech::s_hActor1 = NULL; |
|
CHandle<CASW_Marine> CASW_MarineSpeech::s_hActor2 = NULL; |
|
CHandle<CASW_Marine> CASW_MarineSpeech::s_hCurrentActor = NULL; |
|
static int s_Actor1Indices[ASW_NUM_CONVERSATIONS]={ |
|
0, // CONV_NONE, |
|
ACTOR_CRASH | ACTOR_VEGAS, // CONV_SYNUP, |
|
ACTOR_CRASH, // CONV_CRASH_COMPLAIN, |
|
ACTOR_FAITH | ACTOR_BASTILLE, // CONV_MEDIC_COMPLAIN, |
|
ACTOR_BASTILLE, // CONV_HEALING_CRASH |
|
ACTOR_VEGAS, // CONV_TEQUILA, |
|
ACTOR_CRASH, // CONV_CRASH_IDLE, |
|
ACTOR_FAITH | ACTOR_BASTILLE, // CONV_SERIOUS_INJURY, |
|
ACTOR_JAEGER, // CONV_STILL_BREATHING, |
|
ACTOR_SARGE, // CONV_SARGE_IDLE, |
|
ACTOR_CRASH, // CONV_BIG_ALIEN, |
|
ACTOR_WILDCAT | ACTOR_WOLFE, // CONV_AUTOGUN |
|
ACTOR_WOLFE, // CONV_WOLFE_BEST, |
|
ACTOR_SARGE, // CONV_SARGE_JAEGER_CONV1, (jaeger starts) |
|
ACTOR_JAEGER, // CONV_SARGE_JAEGER_CONV2, (sarge starts) |
|
ACTOR_WILDCAT, // CONV_WILDCAT_KILL, |
|
ACTOR_WOLFE, // CONV_WOLFE_KILL |
|
ACTOR_SARGE, //CONV_COMPLIMENT_JAEGER, // 17 |
|
ACTOR_JAEGER, //CONV_COMPLIMENT_SARGE, // 18 |
|
ACTOR_WILDCAT, //CONV_COMPLIMENT_WOLFE, // 19 |
|
ACTOR_WOLFE, //CONV_COMPLIMENT_WILDCAT, // 20 |
|
}; |
|
|
|
static int s_Actor2Indices[ASW_NUM_CONVERSATIONS]={ |
|
0, // CONV_NONE, |
|
ACTOR_FAITH | ACTOR_BASTILLE, // CONV_SYNUP, |
|
ACTOR_BASTILLE, // CONV_CRASH_COMPLAIN, |
|
ACTOR_ALL, // CONV_MEDIC_COMPLAIN, |
|
ACTOR_CRASH, // CONV_HEALING_CRASH |
|
ACTOR_ALL &~ ACTOR_FLYNN, // CONV_TEQUILA, |
|
ACTOR_SARGE | ACTOR_JAEGER | ACTOR_BASTILLE, // CONV_CRASH_IDLE, |
|
ACTOR_ALL, // CONV_SERIOUS_INJURY, |
|
ACTOR_ALL &~ (ACTOR_SARGE | ACTOR_FLYNN | ACTOR_WOLFE), // CONV_STILL_BREATHING, |
|
ACTOR_SARGE | ACTOR_CRASH, // CONV_SARGE_IDLE, |
|
ACTOR_SARGE, // CONV_BIG_ALIEN, |
|
ACTOR_SARGE | ACTOR_JAEGER, // CONV_AUTOGUN |
|
ACTOR_WILDCAT, // CONV_WOLFE_BEST, |
|
|
|
ACTOR_JAEGER, // CONV_SARGE_JAEGER_CONV1, (sarge is 2nd) |
|
ACTOR_SARGE, // CONV_SARGE_JAEGER_CONV2, (jaeger is 2nd) |
|
ACTOR_WOLFE, // CONV_WILDCAT_KILL, |
|
ACTOR_WILDCAT, // CONV_WOLFE_KILL |
|
ACTOR_JAEGER, //CONV_COMPLIMENT_JAEGER, // 17 |
|
ACTOR_SARGE, //CONV_COMPLIMENT_SARGE, // 18 |
|
ACTOR_WOLFE, //CONV_COMPLIMENT_WOLFE, // 19 |
|
ACTOR_WILDCAT, //CONV_COMPLIMENT_WILDCAT, // 20 |
|
}; |
|
|
|
static int s_ConvChatterLine1[ASW_NUM_CONVERSATIONS]={ |
|
-1, // CONV_NONE, |
|
CHATTER_SYNUP_SPOTTED, // CONV_SYNUP, |
|
CHATTER_CRASH_COMPLAIN, // CONV_CRASH_COMPLAIN, |
|
CHATTER_MEDIC_COMPLAIN, // CONV_MEDIC_COMPLAIN, |
|
CHATTER_HEALING_CRASH, // CONV_HEALING_CRASH |
|
CHATTER_TEQUILA_START, // CONV_TEQUILA, |
|
CHATTER_CRASH_IDLE, // CONV_CRASH_IDLE, |
|
CHATTER_SERIOUS_INJURY, // CONV_SERIOUS_INJURY, |
|
CHATTER_STILL_BREATHING, // CONV_STILL_BREATHING, |
|
CHATTER_SARGE_IDLE, // CONV_SARGE_IDLE, |
|
CHATTER_BIG_ALIEN_DEAD, // CONV_BIG_ALIEN, |
|
CHATTER_AUTOGUN, // CONV_AUTOGUN |
|
CHATTER_WOLFE_BEST, // CONV_WOLFE_BEST, |
|
CHATTER_SARGE_JAEGER_CONV_1, // CONV_SARGE_JAEGER_CONV1, (jaeger starts) |
|
CHATTER_SARGE_JAEGER_CONV_2, // CONV_SARGE_JAEGER_CONV2, (sarge starts) |
|
CHATTER_WILDCAT_KILL, // CONV_WILDCAT_KILL, |
|
CHATTER_WOLFE_KILL, // CONV_WOLFE_KILL |
|
CHATTER_COMPLIMENTS_JAEGER, //CONV_COMPLIMENT_JAEGER, // 17 |
|
CHATTER_COMPLIMENTS_SARGE, //CONV_COMPLIMENT_SARGE, // 18 |
|
CHATTER_COMPLIMENTS_WOLFE, //CONV_COMPLIMENT_WOLFE, // 19 |
|
CHATTER_COMPLIMENTS_WILDCAT, //CONV_COMPLIMENT_WILDCAT, // 20 |
|
}; |
|
|
|
static int s_ConvChatterLine2[ASW_NUM_CONVERSATIONS]={ |
|
-1, // CONV_NONE, |
|
CHATTER_SYNUP_REPLY, // CONV_SYNUP, |
|
CHATTER_CRASH_COMPLAIN_REPLY, // CONV_CRASH_COMPLAIN, |
|
CHATTER_MEDIC_COMPLAIN_REPLY, // CONV_MEDIC_COMPLAIN, |
|
CHATTER_HEALING_CRASH_REPLY, // CONV_HEALING_CRASH |
|
CHATTER_TEQUILA_REPLY, // CONV_TEQUILA, |
|
CHATTER_CRASH_IDLE_REPLY, // CONV_CRASH_IDLE, |
|
CHATTER_SERIOUS_INJURY_REPLY, // CONV_SERIOUS_INJURY, |
|
CHATTER_STILL_BREATHING_REPLY, // CONV_STILL_BREATHING, |
|
CHATTER_SARGE_IDLE_REPLY, // CONV_SARGE_IDLE, |
|
CHATTER_BIG_ALIEN_REPLY, // CONV_BIG_ALIEN, |
|
CHATTER_AUTOGUN_REPLY, // CONV_AUTOGUN |
|
CHATTER_WOLFE_BEST_REPLY, // CONV_WOLFE_BEST, |
|
CHATTER_SARGE_JAEGER_CONV_1_REPLY, // CONV_SARGE_JAEGER_CONV1, (jaeger starts) |
|
CHATTER_SARGE_JAEGER_CONV_2_REPLY, // CONV_SARGE_JAEGER_CONV2, (sarge starts) |
|
CHATTER_WILDCAT_KILL_REPLY_AHEAD, // CONV_WILDCAT_KILL, NOTE: OR BEHIND... |
|
CHATTER_WOLFE_KILL_REPLY_AHEAD, // CONV_WOLFE_KILL |
|
-1, //CONV_COMPLIMENT_JAEGER, // 17 |
|
-1, //CONV_COMPLIMENT_SARGE, // 18 |
|
-1, //CONV_COMPLIMENT_WOLFE, // 19 |
|
-1, //CONV_COMPLIMENT_WILDCAT, // 20 |
|
}; |
|
|
|
static int s_ConvNumStages[ASW_NUM_CONVERSATIONS]={ |
|
0, // CONV_NONE, |
|
2, // CONV_SYNUP, |
|
3, // CONV_CRASH_COMPLAIN, |
|
2, // CONV_MEDIC_COMPLAIN, |
|
3, // CONV_HEALING_CRASH |
|
3, // CONV_TEQUILA, |
|
2, // CONV_CRASH_IDLE, |
|
3, // CONV_SERIOUS_INJURY, |
|
3, // CONV_STILL_BREATHING, |
|
3, // CONV_SARGE_IDLE, |
|
3, // CONV_BIG_ALIEN, // todo:should be 4? |
|
3, // CONV_AUTOGUN |
|
3, // CONV_WOLFE_BEST, |
|
3, // CONV_SARGE_JAEGER_CONV1, (jaeger starts) |
|
3, // CONV_SARGE_JAEGER_CONV2, (sarge starts) |
|
3, // CONV_WILDCAT_KILL, NOTE: OR BEHIND... |
|
3, // CONV_WOLFE_KILL |
|
1, //CONV_COMPLIMENT_JAEGER, // 17 |
|
1, //CONV_COMPLIMENT_SARGE, // 18 |
|
1, //CONV_COMPLIMENT_WOLFE, // 19 |
|
1, //CONV_COMPLIMENT_WILDCAT, // 20 |
|
}; |
|
|
|
/* |
|
CHATTER_TEQUILA_REPLY_SARGE, // Vegas only |
|
CHATTER_TEQUILA_REPLY_JAEGER, // Vegas only |
|
CHATTER_TEQUILA_REPLY_WILDCAT, // Vegas only |
|
CHATTER_TEQUILA_REPLY_WOLFE, // Vegas only |
|
CHATTER_TEQUILA_REPLY_FAITH, // Vegas only |
|
CHATTER_TEQUILA_REPLY_BASTILLE, // Vegas only |
|
|
|
CHATTER_SERIOUS_INJURY_FOLLOW_UP, // faith/bastille only |
|
|
|
CHATTER_FIRST_BLOOD_START, // vegas only |
|
CHATTER_FIRST_BLOOD_WIN, // vegas only |
|
|
|
CHATTER_WILDCAT_KILL_REPLY_BEHIND, |
|
CHATTER_WOLFE_KILL_REPLY_BEHIND, |
|
*/ |
|
|
|
bool CASW_MarineSpeech::StartConversation(int iConversation, CASW_Marine *pMarine, CASW_Marine *pSecondMarine) |
|
{ |
|
if (!pMarine || !pMarine->GetMarineProfile() || iConversation < 0 || iConversation > CONV_COMPLIMENT_WILDCAT |
|
|| pMarine->GetHealth() <= 0 || pMarine->IsInfested() || pMarine->IsOnFire()) |
|
return false; |
|
|
|
if ( !ASWGameResource() ) |
|
return false; |
|
|
|
CASW_Game_Resource *pGameResource = ASWGameResource(); |
|
|
|
// check this marine can start this conversation |
|
if (! ((1 << pMarine->GetMarineProfile()->m_ProfileIndex) & s_Actor1Indices[iConversation]) ) |
|
return false; |
|
|
|
CASW_Marine *pChosen = NULL; |
|
if (pSecondMarine != NULL && pSecondMarine->GetMarineProfile()!=NULL) |
|
{ |
|
// if the other actor was specified, check they can do the conversation |
|
if (! ((1 << pSecondMarine->GetMarineProfile()->m_ProfileIndex) & s_Actor2Indices[iConversation]) ) |
|
return false; |
|
if (pSecondMarine->IsInfested() || pMarine->IsOnFire()) |
|
return false; |
|
pChosen = pSecondMarine; |
|
} |
|
else |
|
{ |
|
// try and find another actor to chat with |
|
int iNearby = 0; |
|
for (int i=0;i<pGameResource->GetMaxMarineResources();i++) |
|
{ |
|
CASW_Marine_Resource *pMR = pGameResource->GetMarineResource(i); |
|
CASW_Marine *pOtherMarine = pMR ? pMR->GetMarineEntity() : NULL; |
|
if (pOtherMarine && pOtherMarine != pMarine && (pOtherMarine->GetAbsOrigin().DistTo(pMarine->GetAbsOrigin()) < 600) |
|
&& pOtherMarine->GetHealth() > 0 && !pOtherMarine->IsInfested() && !pOtherMarine->IsOnFire() && pOtherMarine->GetMarineProfile() |
|
&& ((1 << pOtherMarine->GetMarineProfile()->m_ProfileIndex) & s_Actor2Indices[iConversation]) ) |
|
iNearby++; |
|
} |
|
if (iNearby > 0) |
|
{ |
|
int iChosen = random->RandomInt(0, iNearby-1); |
|
for (int i=0;i<pGameResource->GetMaxMarineResources();i++) |
|
{ |
|
CASW_Marine_Resource *pMR = pGameResource->GetMarineResource(i); |
|
CASW_Marine *pOtherMarine = pMR ? pMR->GetMarineEntity() : NULL; |
|
if (pOtherMarine && pOtherMarine != pMarine && (pOtherMarine->GetAbsOrigin().DistTo(pMarine->GetAbsOrigin()) < 600) |
|
&& pOtherMarine->GetHealth() > 0 && !pOtherMarine->IsInfested() && !pOtherMarine->IsOnFire() && pOtherMarine->GetMarineProfile() |
|
&& ((1 << pOtherMarine->GetMarineProfile()->m_ProfileIndex) & s_Actor2Indices[iConversation]) ) |
|
{ |
|
if (iChosen <= 0) |
|
{ |
|
pChosen = pOtherMarine; |
|
break; |
|
} |
|
iChosen--; |
|
} |
|
} |
|
} |
|
} |
|
if (!pChosen && iConversation != CONV_SYNUP) // synup doesn't need 2 people to start the conv |
|
return false; |
|
|
|
if (asw_debug_marine_chatter.GetBool()) |
|
Msg("%f: Starting conv %d successfully, between marines %s and %s\n", gpGlobals->curtime, iConversation, pMarine->GetMarineProfile()->m_ShortName, |
|
pChosen ? pChosen->GetMarineProfile()->m_ShortName : "no-one"); |
|
s_CurrentConversation = iConversation; |
|
s_CurrentConversationChatterStage = 0; |
|
s_hCurrentActor = pMarine; |
|
s_hActor1 = pMarine; |
|
s_hActor2 = pChosen; |
|
s_iCurrentConvLine = s_ConvChatterLine1[iConversation]; |
|
pMarine->GetMarineSpeech()->QueueChatter(s_iCurrentConvLine, gpGlobals->curtime, gpGlobals->curtime + 5.0f); |
|
return true; |
|
} |
|
|
|
void CASW_MarineSpeech::StopConversation() |
|
{ |
|
if (asw_debug_marine_chatter.GetBool()) |
|
Msg("Stopping conversation"); |
|
s_CurrentConversation = CONV_NONE; |
|
s_CurrentConversationChatterStage = 0; |
|
s_hCurrentActor = NULL; |
|
s_hActor1 = NULL; |
|
s_hActor2 = NULL; |
|
} |
|
|
|
CASW_MarineSpeech::CASW_MarineSpeech(CASW_Marine *pMarine) |
|
{ |
|
m_pMarine = pMarine; |
|
m_fPersonalChatterTime = 0; |
|
m_SpeechQueue.Purge(); |
|
m_fFriendlyFireTime = 0; |
|
} |
|
|
|
CASW_MarineSpeech::~CASW_MarineSpeech() |
|
{ |
|
|
|
} |
|
|
|
bool CASW_MarineSpeech::TranslateChatter(int &iChatterType, CASW_Marine_Profile *pProfile) |
|
{ |
|
if (!pProfile) |
|
return false; |
|
// special holding position translations |
|
if (iChatterType == CHATTER_HOLDING_POSITION) |
|
{ |
|
if (random->RandomFloat() < ASW_DIRECTIONAL_HOLDING_CHATTER) |
|
FindDirectionalHoldingChatter(iChatterType); |
|
} |
|
// random chance of playing some chatters |
|
else if (iChatterType == CHATTER_SELECTION) |
|
{ |
|
// check for using injured version |
|
if (m_pMarine->IsWounded()) |
|
iChatterType = CHATTER_SELECTION_INJURED; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
bool CASW_MarineSpeech::ForceChatter(int iChatterType, int iTimerType) |
|
{ |
|
if (!m_pMarine || !m_pMarine->GetMarineResource() || (m_pMarine->GetHealth()<=0 && iChatterType != CHATTER_DIE)) |
|
return false; |
|
|
|
CASW_Marine_Profile *pProfile = m_pMarine->GetMarineResource()->GetProfile(); |
|
if (!pProfile) |
|
return false; |
|
|
|
if (!TranslateChatter(iChatterType, pProfile)) |
|
return false; |
|
|
|
// check for discarding chatter if it only has a random chance of playing and we don't hit |
|
if (random->RandomFloat() > pProfile->m_fChatterChance[iChatterType]) |
|
return true; |
|
|
|
// if marine doesn't have this line, then don't try playing it |
|
const char *szChatter = pProfile->m_Chatter[iChatterType]; |
|
if (szChatter[0] == '\0') |
|
return false; |
|
|
|
InternalPlayChatter(m_pMarine, szChatter, iTimerType, iChatterType); |
|
return true; |
|
} |
|
|
|
bool CASW_MarineSpeech::Chatter(int iChatterType, int iSubChatter, CBasePlayer *pOnlyForPlayer) |
|
{ |
|
if (iChatterType < 0 || iChatterType >= NUM_CHATTER_LINES) |
|
{ |
|
AssertMsg1( false, "Faulty chatter type %d\n", iChatterType ); |
|
return false; |
|
} |
|
|
|
if (!m_pMarine || !m_pMarine->GetMarineResource() || (m_pMarine->GetHealth()<=0 && iChatterType != CHATTER_DIE)) |
|
{ |
|
AssertMsg( false, "Absent marine tried to chatter\n" ); |
|
return false; |
|
} |
|
|
|
CASW_Marine_Profile *pProfile = m_pMarine->GetMarineResource()->GetProfile(); |
|
if (!pProfile) |
|
{ |
|
AssertMsg1( false, "Marine %s is missing a profile\n", m_pMarine->GetDebugName() ); |
|
return false; |
|
} |
|
|
|
if (gpGlobals->curtime < GetTeamChatterTime()) |
|
return false; |
|
|
|
if (!TranslateChatter(iChatterType, pProfile)) |
|
return false; |
|
|
|
// check for discarding chatter if some marines are in the middle of a conversation |
|
if (s_CurrentConversation != CONV_NONE) |
|
{ |
|
CASW_Marine *pCurrentActor = (s_CurrentConversationChatterStage == 1) ? s_hActor2.Get() : s_hActor1.Get(); |
|
int iCurrentConvLine = s_iCurrentConvLine; |
|
// if this isn't the right speaker saying the right line... |
|
if (iChatterType != iCurrentConvLine || m_pMarine != pCurrentActor) |
|
return false; |
|
} |
|
|
|
// check for discarding chatter if it only has a random chance of playing and we don't hit |
|
if (random->RandomFloat() > pProfile->m_fChatterChance[iChatterType]) |
|
return true; |
|
|
|
if (iChatterType == CHATTER_FIRING_AT_ALIEN) |
|
{ |
|
if (gpGlobals->curtime < GetIncomingChatterTime()) |
|
return false; |
|
|
|
SetIncomingChatterTime(gpGlobals->curtime + ASW_INTERVAL_CHATTER_INCOMING); |
|
} |
|
|
|
// if marine doesn't have this line, then don't try playing it |
|
const char *szChatter = pProfile->m_Chatter[iChatterType]; |
|
if (szChatter[0] == '\0') |
|
return false; |
|
|
|
InternalPlayChatter(m_pMarine, szChatter, ASW_CHATTER_TIMER_TEAM, iChatterType, iSubChatter, pOnlyForPlayer); |
|
return true; |
|
} |
|
|
|
bool CASW_MarineSpeech::PersonalChatter(int iChatterType) |
|
{ |
|
if (iChatterType < 0 || iChatterType >= NUM_CHATTER_LINES) |
|
return false; |
|
|
|
if (!m_pMarine || !m_pMarine->GetMarineResource() || (m_pMarine->GetHealth()<=0 && iChatterType != CHATTER_DIE)) |
|
return false; |
|
|
|
CASW_Marine_Profile *pProfile = m_pMarine->GetMarineResource()->GetProfile(); |
|
if (!pProfile) |
|
return false; |
|
|
|
if (gpGlobals->curtime < GetPersonalChatterTime()) |
|
return false; |
|
|
|
if (!TranslateChatter(iChatterType, pProfile)) |
|
return false; |
|
|
|
// check for discarding chatter if it only has a random chance of playing and we don't hit |
|
if (random->RandomFloat() > pProfile->m_fChatterChance[iChatterType]) |
|
return true; |
|
|
|
// if marine doesn't have this line, then don't try playing it |
|
const char *szChatter = pProfile->m_Chatter[iChatterType]; |
|
if (szChatter[0] == '\0') |
|
return false; |
|
|
|
InternalPlayChatter(m_pMarine, szChatter, ASW_CHATTER_TIMER_PERSONAL, iChatterType); |
|
return true; |
|
} |
|
|
|
|
|
void CASW_MarineSpeech::InternalPlayChatter(CASW_Marine* pMarine, const char* szSoundName, int iSetTimer, int iChatterType, int iSubChatter, CBasePlayer *pOnlyForPlayer) |
|
{ |
|
if (!pMarine || !ASWGameRules() || iSubChatter >= NUM_SUB_CHATTERS) |
|
return; |
|
|
|
if (ASWGameRules()->GetGameState() > ASW_GS_INGAME) |
|
return; |
|
|
|
// only allow certain chatters when marine is on fire |
|
if (pMarine->IsOnFire()) |
|
{ |
|
if (iChatterType != CHATTER_FRIENDLY_FIRE && |
|
iChatterType != CHATTER_MEDIC && |
|
iChatterType != CHATTER_INFESTED && |
|
iChatterType != CHATTER_PAIN_SMALL && |
|
iChatterType != CHATTER_PAIN_LARGE && |
|
iChatterType != CHATTER_DIE && |
|
iChatterType != CHATTER_ON_FIRE) |
|
return; |
|
} |
|
|
|
if (asw_debug_marine_chatter.GetBool()) |
|
Msg("%s playing chatter %s %d\n", pMarine->GetMarineProfile()->m_ShortName, szSoundName, iChatterType); |
|
|
|
// select a sub chatter |
|
int iMaxChatter = pMarine->GetMarineProfile()->m_iChatterCount[iChatterType]; |
|
if (iMaxChatter <= 0) |
|
{ |
|
Msg("Warning, couldn't play chatter of type %d as no sub chatters of that type for this marine\n", iChatterType); |
|
return; |
|
} |
|
if (iSubChatter < 0) |
|
iSubChatter = random->RandomInt(0, iMaxChatter - 1); |
|
|
|
// asw temp comment |
|
CPASAttenuationFilter filter( pMarine ); |
|
//CSoundParameters params; |
|
//char chatterbuffer[128]; |
|
//Q_snprintf(chatterbuffer, sizeof(chatterbuffer), "%s%d", szSoundName, iSubChatter); |
|
//if ( pMarine->GetParametersForSound( chatterbuffer, params, NULL ) ) |
|
{ |
|
//if (!params.soundname[0]) |
|
//return; |
|
|
|
if (iSetTimer != ASW_CHATTER_TIMER_NONE) |
|
{ |
|
// asw temp comment |
|
//char *skipped = PSkipSoundChars( params.soundname ); |
|
//float duration = enginesound->GetSoundDuration( skipped ); |
|
//Msg("ingame duration for sound %s is %f\n", skipped, duration); |
|
float duration = pMarine->GetMarineProfile()->m_fChatterDuration[iChatterType][iSubChatter]; |
|
if (iSetTimer == ASW_CHATTER_TIMER_TEAM) |
|
{ |
|
// make sure no one else talks until this is done |
|
SetTeamChatterTime(gpGlobals->curtime + duration); |
|
SetPersonalChatterTime(gpGlobals->curtime + duration); |
|
} |
|
else // ASW_CHATTER_TIMER_PERSONAL |
|
{ |
|
SetPersonalChatterTime(gpGlobals->curtime + duration); |
|
} |
|
} |
|
|
|
//EmitSound_t ep( params ); |
|
//pMarine->EmitSound( filter, pMarine->entindex(), ep ); |
|
|
|
|
|
// user messages based speech |
|
CEffectData data; |
|
|
|
data.m_vOrigin = pMarine->GetAbsOrigin(); |
|
data.m_nEntIndex = pMarine->entindex(); |
|
data.m_nDamageType = iChatterType; |
|
data.m_nMaterial = iSubChatter; |
|
|
|
if (!pOnlyForPlayer) |
|
{ |
|
CPASFilter filter( data.m_vOrigin ); |
|
filter.SetIgnorePredictionCull(true); |
|
DispatchEffect( filter, 0.0, "ASWSpeech", data ); |
|
} |
|
else |
|
{ |
|
CSingleUserRecipientFilter filter( pOnlyForPlayer ); |
|
filter.SetIgnorePredictionCull(true); |
|
DispatchEffect( filter, 0.0, "ASWSpeech", data ); |
|
} |
|
} |
|
} |
|
|
|
void CASW_MarineSpeech::Precache() |
|
{ |
|
if (!m_pMarine || !m_pMarine->GetMarineResource()) |
|
{ |
|
//Msg("Error: Attempted to precache marine speech when either marine is null or marine has no marine resource."); |
|
return; |
|
} |
|
|
|
CASW_Marine_Profile *profile= m_pMarine->GetMarineResource()->GetProfile(); |
|
// asw temp comment of speech |
|
profile->PrecacheSpeech(m_pMarine); |
|
} |
|
|
|
float CASW_MarineSpeech::GetTeamChatterTime() |
|
{ |
|
if (!ASWGameRules()) |
|
return 0; |
|
|
|
return ASWGameRules()->GetChatterTime(); |
|
} |
|
|
|
float CASW_MarineSpeech::GetIncomingChatterTime() |
|
{ |
|
if (!ASWGameRules()) |
|
return 0; |
|
|
|
return ASWGameRules()->GetIncomingChatterTime(); |
|
} |
|
|
|
void CASW_MarineSpeech::SetTeamChatterTime(float f) |
|
{ |
|
if ( asw_debug_marine_chatter.GetBool() ) |
|
Msg( "%f:SetTeamChatterTime %f\n", gpGlobals->curtime, f ); |
|
if (ASWGameRules()) |
|
ASWGameRules()->SetChatterTime(f); |
|
} |
|
|
|
void CASW_MarineSpeech::SetIncomingChatterTime(float f) |
|
{ |
|
if ( asw_debug_marine_chatter.GetBool() ) |
|
Msg( "%f:SetIncomingChatterTime %f\n", gpGlobals->curtime, f ); |
|
if (ASWGameRules()) |
|
ASWGameRules()->SetIncomingChatterTime(f); |
|
} |
|
|
|
void CASW_MarineSpeech::SetPersonalChatterTime(float f) |
|
{ |
|
if ( asw_debug_marine_chatter.GetBool() ) |
|
Msg( "%f:SetPersonalChatterTime %f\n", gpGlobals->curtime, f ); |
|
m_fPersonalChatterTime = f; |
|
} |
|
|
|
bool CASW_MarineSpeech::FindDirectionalHoldingChatter(int &iChatterType) |
|
{ |
|
if ( !m_pMarine ) |
|
return false; |
|
|
|
Vector vecFacing; |
|
QAngle angHolding(0, m_pMarine->GetHoldingYaw(), 0); |
|
AngleVectors(angHolding, &vecFacing); |
|
|
|
// first check there's no other marines standing in front of us |
|
CASW_Game_Resource *pGameResource = ASWGameResource(); |
|
if (!pGameResource) |
|
return false; |
|
int m = pGameResource->GetMaxMarineResources(); |
|
for (int i=0;i<m;i++) |
|
{ |
|
CASW_Marine_Resource *pMR = pGameResource->GetMarineResource(i); |
|
if (!pMR || !pMR->GetMarineEntity()) |
|
continue; |
|
|
|
CASW_Marine *pOtherMarine = pMR->GetMarineEntity(); |
|
Vector diff = pOtherMarine->GetAbsOrigin() - m_pMarine->GetAbsOrigin(); |
|
if (diff.Length() > 1000) // if they're too far away, don't count them as blocking our covering area |
|
continue; |
|
|
|
// check they're in front |
|
diff.z = 0; |
|
diff.NormalizeInPlace(); |
|
if (diff.Dot(vecFacing) < 0.3f) |
|
continue; |
|
|
|
// this marine is in front, so we can't do a directional shout |
|
return false; |
|
} |
|
|
|
// do a few traces to roughly check we're not facing a wall |
|
trace_t tr; |
|
if (asw_debug_marine_chatter.GetBool()) |
|
NDebugOverlay::Line( m_pMarine->WorldSpaceCenter(), m_pMarine->WorldSpaceCenter() + vecFacing * 300.0f, 255, 0, 0, false, 5.0f ); |
|
UTIL_TraceLine(m_pMarine->WorldSpaceCenter(), m_pMarine->WorldSpaceCenter() + vecFacing * 300.0f, MASK_SOLID, m_pMarine, COLLISION_GROUP_NONE, &tr); |
|
if (tr.fraction < 1.0f) |
|
return false; |
|
|
|
angHolding[YAW] += 30; |
|
AngleVectors(angHolding, &vecFacing); |
|
if (asw_debug_marine_chatter.GetBool()) |
|
NDebugOverlay::Line( m_pMarine->WorldSpaceCenter(), m_pMarine->WorldSpaceCenter() + vecFacing * 200.0f, 255, 0, 0, false, 5.0f ); |
|
UTIL_TraceLine(m_pMarine->WorldSpaceCenter(), m_pMarine->WorldSpaceCenter() + vecFacing * 200.0f, MASK_SOLID, m_pMarine, COLLISION_GROUP_NONE, &tr); |
|
if (tr.fraction < 1.0f) |
|
return false; |
|
|
|
angHolding[YAW] -= 60; |
|
AngleVectors(angHolding, &vecFacing); |
|
if (asw_debug_marine_chatter.GetBool()) |
|
NDebugOverlay::Line( m_pMarine->WorldSpaceCenter(), m_pMarine->WorldSpaceCenter() + vecFacing * 200.0f, 255, 0, 0, false, 5.0f ); |
|
UTIL_TraceLine(m_pMarine->WorldSpaceCenter(), m_pMarine->WorldSpaceCenter() + vecFacing * 200.0f, MASK_SOLID, m_pMarine, COLLISION_GROUP_NONE, &tr); |
|
if (tr.fraction < 1.0f) |
|
return false; |
|
|
|
// okay, we're good to do a directional, let's see which one to do |
|
float fYaw = anglemod(m_pMarine->GetHoldingYaw()); |
|
if (fYaw < 40 || fYaw > 320) |
|
iChatterType = CHATTER_HOLDING_EAST; |
|
else if (fYaw > 50 && fYaw < 130) |
|
iChatterType = CHATTER_HOLDING_NORTH; |
|
else if (fYaw > 140 && fYaw < 220) |
|
iChatterType = CHATTER_HOLDING_WEST; |
|
else if (fYaw > 230 && fYaw < 310) |
|
iChatterType = CHATTER_HOLDING_SOUTH; |
|
else |
|
return false; // wasn't facing close enough to a cardinal |
|
|
|
return true; |
|
} |
|
|
|
void CASW_MarineSpeech::QueueChatter(int iChatterType, float fPlayTime, float fMaxPlayTime, CBasePlayer *pOnlyForPlayer) |
|
{ |
|
if (!m_pMarine || m_pMarine->GetHealth() <= 0) |
|
return; |
|
// check this speech isn't already in the queue |
|
int iCount = m_SpeechQueue.Count(); |
|
for (int i=iCount-1;i>=0;i--) |
|
{ |
|
if (m_SpeechQueue[i].iChatterType == iChatterType) |
|
return; |
|
} |
|
|
|
if (iChatterType == CHATTER_HOLDING_POSITION) // if marine is holding |
|
{ |
|
int iCount = m_SpeechQueue.Count(); |
|
for (int i=iCount-1;i>=0;i--) |
|
{ |
|
if (m_SpeechQueue[i].iChatterType == CHATTER_USE) // then remove any 'confirming move order' type speech queued up |
|
m_SpeechQueue.Remove(i); |
|
} |
|
} |
|
else if (iChatterType == CHATTER_USE) // if marine is confirming move order |
|
{ |
|
int iCount = m_SpeechQueue.Count(); |
|
for (int i=iCount-1;i>=0;i--) |
|
{ |
|
if (m_SpeechQueue[i].iChatterType == CHATTER_HOLDING_POSITION) // then remove any holding position speech queued up |
|
m_SpeechQueue.Remove(i); |
|
} |
|
} |
|
|
|
// don't FF fire too frequently |
|
if (iChatterType == CHATTER_FRIENDLY_FIRE) |
|
{ |
|
if (gpGlobals->curtime < m_fFriendlyFireTime) |
|
return; |
|
|
|
m_fFriendlyFireTime = gpGlobals->curtime + ASW_INTERVAL_FF; |
|
} |
|
if (asw_debug_marine_chatter.GetBool()) |
|
Msg("%f: queuing speech %d at time %f\n", gpGlobals->curtime, iChatterType, fPlayTime); |
|
CASW_Queued_Speech entry; |
|
entry.iChatterType = iChatterType; |
|
entry.fPlayTime = fPlayTime; |
|
entry.fMaxPlayTime = fMaxPlayTime; |
|
entry.hOnlyForPlayer = pOnlyForPlayer; |
|
m_SpeechQueue.AddToTail(entry); |
|
} |
|
|
|
void CASW_MarineSpeech::Update() |
|
{ |
|
if (!m_pMarine) |
|
return; |
|
|
|
int iCount = m_SpeechQueue.Count(); |
|
|
|
// loop backwards because we might remove one |
|
for (int i=iCount-1;i>=0;i--) |
|
{ |
|
if (gpGlobals->curtime >= m_SpeechQueue[i].fPlayTime) |
|
{ |
|
// try to play the queued speech |
|
if (asw_debug_marine_chatter.GetBool()) |
|
Msg("%f: trying to play queued speech %d\n", gpGlobals->curtime, m_SpeechQueue[i].iChatterType); |
|
bool bPlay = true; |
|
|
|
if ((m_SpeechQueue[i].iChatterType == CHATTER_HOLDING_POSITION |
|
|| m_SpeechQueue[i].iChatterType == CHATTER_USE) |
|
&& m_pMarine->IsInhabited()) |
|
{ |
|
bPlay = false; |
|
} |
|
|
|
if (!bPlay) |
|
{ |
|
if (asw_debug_marine_chatter.GetBool()) |
|
Msg(" removing queued speech; inappropriate to play it now (marine probably inhabited and this is an AI line)\n"); |
|
m_SpeechQueue.Remove(i); |
|
continue; |
|
} |
|
|
|
if (Chatter(m_SpeechQueue[i].iChatterType, -1, m_SpeechQueue[i].hOnlyForPlayer.Get())) |
|
{ |
|
if (s_CurrentConversation != CONV_NONE) |
|
{ |
|
CASW_Marine *pCurrentActor = (s_CurrentConversationChatterStage == 1) ? s_hActor2.Get() : s_hActor1.Get(); |
|
int iCurrentConvLine = s_iCurrentConvLine; |
|
// if we just finished the currently queued conversation line... |
|
if (m_SpeechQueue[i].iChatterType == iCurrentConvLine && m_pMarine == pCurrentActor) |
|
{ |
|
s_CurrentConversationChatterStage++; |
|
int iNumStages = s_ConvNumStages[s_CurrentConversation]; |
|
|
|
|
|
/* |
|
CHATTER_WILDCAT_KILL_REPLY_BEHIND, |
|
CHATTER_WOLFE_KILL_REPLY_BEHIND, |
|
*/ |
|
|
|
// check all the actors are alive still, etc and we're not at the end of the conversation |
|
if (s_CurrentConversationChatterStage >= iNumStages |
|
|| !s_hActor1.Get() || s_hActor1.Get()->GetHealth()<=0 |
|
|| !s_hActor2.Get() || s_hActor2.Get()->GetHealth()<=0) |
|
{ |
|
StopConversation(); |
|
} |
|
else |
|
{ |
|
// queue up the next line |
|
pCurrentActor = (s_CurrentConversationChatterStage == 1) ? s_hActor2.Get() : s_hActor1.Get(); |
|
iCurrentConvLine = (s_CurrentConversationChatterStage == 0) ? s_ConvChatterLine1[s_CurrentConversation] : s_ConvChatterLine2[s_CurrentConversation]; |
|
// make wolfe/wildcat pick the right line in their conv |
|
if (s_CurrentConversation == CONV_WILDCAT_KILL) |
|
{ |
|
if (asw_debug_marine_chatter.GetBool()) |
|
Msg("CONV_WILDCAT_KILL, stage %d\n", s_CurrentConversationChatterStage); |
|
if (s_CurrentConversationChatterStage == 1) // wolfe replying, does he have more or less kills |
|
{ |
|
if (GetWildcatAhead()) |
|
iCurrentConvLine = CHATTER_WILDCAT_KILL_REPLY_BEHIND; |
|
else |
|
iCurrentConvLine = CHATTER_WILDCAT_KILL_REPLY_AHEAD; |
|
} |
|
else if (s_CurrentConversationChatterStage == 2) // wildcat following up |
|
{ |
|
if (GetWildcatAhead()) |
|
iCurrentConvLine = CHATTER_WILDCAT_KILL_REPLY_AHEAD; |
|
else |
|
iCurrentConvLine = CHATTER_WILDCAT_KILL_REPLY_BEHIND; |
|
} |
|
} |
|
else if (s_CurrentConversation == CONV_WOLFE_KILL) |
|
{ |
|
if (asw_debug_marine_chatter.GetBool()) |
|
Msg("CONV_WILDCAT_KILL, stage %d\n", s_CurrentConversationChatterStage); |
|
if (s_CurrentConversationChatterStage == 1) // wildcat replying, does he have more or less kills |
|
{ |
|
if (GetWildcatAhead()) |
|
iCurrentConvLine = CHATTER_WOLFE_KILL_REPLY_AHEAD; |
|
else |
|
iCurrentConvLine = CHATTER_WOLFE_KILL_REPLY_BEHIND; |
|
} |
|
else if (s_CurrentConversationChatterStage == 2) // wolfe following up |
|
{ |
|
if (GetWildcatAhead()) |
|
iCurrentConvLine = CHATTER_WOLFE_KILL_REPLY_BEHIND; |
|
else |
|
iCurrentConvLine = CHATTER_WOLFE_KILL_REPLY_AHEAD; |
|
} |
|
} |
|
|
|
if (s_CurrentConversationChatterStage == 2) |
|
{ |
|
if (s_CurrentConversation == CONV_TEQUILA && s_hActor2.Get()->GetMarineProfile()) |
|
{ |
|
int iProfileIndex = s_hActor2.Get()->GetMarineProfile()->m_ProfileIndex; |
|
// change the line to one appropriate for who we're talking to |
|
if (iProfileIndex == 0) iCurrentConvLine = CHATTER_TEQUILA_REPLY_SARGE; |
|
else if (iProfileIndex == 4) iCurrentConvLine = CHATTER_TEQUILA_REPLY_JAEGER; |
|
else if (iProfileIndex == 1) iCurrentConvLine = CHATTER_TEQUILA_REPLY_WILDCAT; |
|
else if (iProfileIndex == 5) iCurrentConvLine = CHATTER_TEQUILA_REPLY_WOLFE; |
|
else if (iProfileIndex == 2) iCurrentConvLine = CHATTER_TEQUILA_REPLY_FAITH; |
|
else if (iProfileIndex == 6) iCurrentConvLine = CHATTER_TEQUILA_REPLY_BASTILLE; |
|
else iCurrentConvLine = -1; |
|
} |
|
else if (s_CurrentConversation == CONV_SERIOUS_INJURY) |
|
{ |
|
iCurrentConvLine = CHATTER_SERIOUS_INJURY_FOLLOW_UP; |
|
} |
|
} |
|
|
|
if (iCurrentConvLine == -1 || s_hActor2.Get()==NULL) |
|
StopConversation(); |
|
else |
|
{ |
|
if (asw_debug_marine_chatter.GetBool()) |
|
Msg("Queuing up the next line in this conversation %d\n", iCurrentConvLine); |
|
s_iCurrentConvLine = iCurrentConvLine; |
|
pCurrentActor->GetMarineSpeech()->QueueChatter(iCurrentConvLine, GetTeamChatterTime() + 0.05f, GetTeamChatterTime() + 60.0f); |
|
} |
|
} |
|
} |
|
} |
|
if (asw_debug_marine_chatter.GetBool()) |
|
Msg(" and removing the speech (%d) since it played ok (or failed the chance to play)\n", m_SpeechQueue[i].iChatterType); |
|
m_SpeechQueue.Remove(i); |
|
} |
|
else |
|
{ |
|
if (asw_debug_marine_chatter.GetBool()) |
|
Msg(" didn't play ok, trying to requeue\n"); |
|
m_SpeechQueue[i].fPlayTime = GetTeamChatterTime() + 0.05f; // try and queue it up for when we next have a gap |
|
if (m_SpeechQueue[i].fPlayTime > m_SpeechQueue[i].fMaxPlayTime) // if it's too late, then abort |
|
{ |
|
if (asw_debug_marine_chatter.GetBool()) |
|
Msg(" but out of time!\n"); |
|
m_SpeechQueue.Remove(i); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
bool CASW_MarineSpeech::GetWildcatAhead() |
|
{ |
|
int iWildcatKills = 0; |
|
int iWolfeKills = 0; |
|
|
|
if ( !ASWGameResource() ) |
|
return false; |
|
|
|
CASW_Game_Resource *pGameResource = ASWGameResource(); |
|
for (int i=0;i<pGameResource->GetMaxMarineResources();i++) |
|
{ |
|
CASW_Marine_Resource *pMR = pGameResource->GetMarineResource(i); |
|
|
|
if (pMR && pMR->GetProfile() && pMR->GetProfile()->m_VoiceType == ASW_VOICE_WILDCAT) |
|
iWildcatKills = pMR->m_iAliensKilled; |
|
else if (pMR && pMR->GetProfile() && pMR->GetProfile()->m_VoiceType == ASW_VOICE_WOLFE) |
|
iWolfeKills = pMR->m_iAliensKilled; |
|
} |
|
return iWildcatKills > iWolfeKills; |
|
} |
|
|
|
struct MarineFlavorSpeech |
|
{ |
|
unsigned char uchChatterType; |
|
unsigned char uchSubChatter; |
|
}; |
|
|
|
const int g_nNumFlavorSpeech = 25; |
|
|
|
MarineFlavorSpeech g_MarineFlavorSpeech[ g_nNumFlavorSpeech ][ ASW_VOICE_TYPE_TOTAL ] = |
|
{ |
|
{ |
|
{ 44, 1 }, // Sarge |
|
{ 1,0 }, // Jaeger |
|
{ 3,1 }, // Wildcat |
|
{ 0,0 }, // Wolf |
|
{ 0,1 }, // Faith |
|
{ 2,2 }, // Bastille |
|
{ 0,1 }, // Crash |
|
{ 0,0 }, // Flynn |
|
{ 0,1 }, // Vegas |
|
}, |
|
{ |
|
{ 123, 0 }, // Sarge |
|
{ 3,5 }, // Jaeger |
|
{ 3,2 }, // Wildcat |
|
{ 1,0 }, // Wolf |
|
{ 1,3 }, // Faith |
|
{ 2,3 }, // Bastille |
|
{ 1,1 }, // Crash |
|
{ 1,1 }, // Flynn |
|
{ 1,2 }, // Vegas |
|
}, |
|
{ |
|
{ 123, 2 }, // Sarge |
|
{ 3,10 }, // Jaeger |
|
{ 3,4 }, // Wildcat |
|
{ 1,3 }, // Wolf |
|
{ 2,2 }, // Faith |
|
{ 3,0 }, // Bastille |
|
{ 2,0 }, // Crash |
|
{ 3,0 }, // Flynn |
|
{ 2,1 }, // Vegas |
|
}, |
|
{ |
|
{ 104, 0 }, // Sarge |
|
{ 3,12 }, // Jaeger |
|
{ 3,5 }, // Wildcat |
|
{ 2,0 }, // Wolf |
|
{ 2,0 }, // Faith |
|
{ 3,8 }, // Bastille |
|
{ 3,3 }, // Crash |
|
{ 3,2 }, // Flynn |
|
{ 3,0 }, // Vegas |
|
}, |
|
{ |
|
{ 104, 1 }, // Sarge |
|
{ 3,13 }, // Jaeger |
|
{ 3,6 }, // Wildcat |
|
{ 3,1 }, // Wolf |
|
{ 3,4 }, // Faith |
|
{ 3,10 }, // Bastille |
|
{ 3,4 }, // Crash |
|
{ 123,0 }, // Flynn |
|
{ 3,2 }, // Vegas |
|
}, |
|
{ |
|
{ 114, 1 }, // Sarge |
|
{ 3,9 }, // Jaeger |
|
{ 0,0 }, // Wildcat |
|
{ 3,0 }, // Wolf |
|
{ 3,7 }, // Faith |
|
{ 3,11 }, // Bastille |
|
{ 27,2 }, // Crash |
|
{ 3,5 }, // Flynn |
|
{ 3,8 }, // Vegas |
|
}, |
|
{ |
|
{ 2, 2 }, // Sarge |
|
{ 3,7 }, // Jaeger |
|
{ 1,2 }, // Wildcat |
|
{ 3,2 }, // Wolf |
|
{ 3,3 }, // Faith |
|
{ 3,13 }, // Bastille |
|
{ 54,3 }, // Crash |
|
{ 3,3 }, // Flynn |
|
{ 3,5 }, // Vegas |
|
}, |
|
{ |
|
{ 3, 5 }, // Sarge |
|
{ 3,6 }, // Jaeger |
|
{ 45,1 }, // Wildcat |
|
{ 3,3 }, // Wolf |
|
{ 3,8 }, // Faith |
|
{ 3,0 }, // Bastille |
|
{ 72,4 }, // Crash |
|
{ 3,1 }, // Flynn |
|
{ 6,3 }, // Vegas |
|
}, |
|
{ |
|
{ 3, 7 }, // Sarge |
|
{ 3,2 }, // Jaeger |
|
{ 54,1 }, // Wildcat |
|
{ 3,6 }, // Wolf |
|
{ 3,9 }, // Faith |
|
{ 3,15 }, // Bastille |
|
{ 73,1 }, // Crash |
|
{ 5,3 }, // Flynn |
|
{ 45,1 }, // Vegas |
|
}, |
|
{ |
|
{ 3, 8 }, // Sarge |
|
{ 5,2 }, // Jaeger |
|
{ 61,0 }, // Wildcat |
|
{ 3,4 }, // Wolf |
|
{ 54,2 }, // Faith |
|
{ 3,5 }, // Bastille |
|
{ 75,4 }, // Crash |
|
{ 75,0 }, // Flynn |
|
{ 47,2 }, // Vegas |
|
}, |
|
{ |
|
{ 3, 12 }, // Sarge |
|
{ 54,3 }, // Jaeger |
|
{ 3,3 }, // Wildcat |
|
{ 3,5 }, // Wolf |
|
{ 54,3 }, // Faith |
|
{ 45,2 }, // Bastille |
|
{ 75,4 }, // Crash |
|
{ 61,0 }, // Flynn |
|
{ 54,2 }, // Vegas |
|
}, |
|
{ |
|
{ 3, 2 }, // Sarge |
|
{ 54,4 }, // Jaeger |
|
{ 108,1 }, // Wildcat |
|
{ 3,6 }, // Wolf |
|
{ 71,2 }, // Faith |
|
{ 54,1 }, // Bastille |
|
{ 61,2 }, // Crash |
|
{ 123,0 }, // Flynn |
|
{ 54,0 }, // Vegas |
|
}, |
|
{ |
|
{ 3, 9 }, // Sarge |
|
{ 108,0 }, // Jaeger |
|
{ 63,0 }, // Wildcat |
|
{ 66,2 }, // Wolf |
|
{ 84,1 }, // Faith |
|
{ 69,13 }, // Bastille |
|
{ 82,0 }, // Crash |
|
{ 85,0 }, // Flynn |
|
{ 54,3 }, // Vegas |
|
}, |
|
{ |
|
{ 47, 1 }, // Sarge |
|
{ 101,0 }, // Jaeger |
|
{ 4,0 }, // Wildcat |
|
{ 123,3 }, // Wolf |
|
{ 0,1 }, // Faith |
|
{ 69,18 }, // Bastille |
|
{ 96,0 }, // Crash |
|
{ 0,0 }, // Flynn |
|
{ 72,0 }, // Vegas |
|
}, |
|
{ |
|
{ 52, 2 }, // Sarge |
|
{ 1,0 }, // Jaeger |
|
{ 3,1 }, // Wildcat |
|
{ 110,8 }, // Wolf |
|
{ 1,3 }, // Faith |
|
{ 69,10 }, // Bastille |
|
{ 2,1 }, // Crash |
|
{ 85, }, // Flynn |
|
{ 73,7 }, // Vegas |
|
}, |
|
{ |
|
{ 3, 13 }, // Sarge |
|
{ 3,5 }, // Jaeger |
|
{ 3,2 }, // Wildcat |
|
{ 85,0 }, // Wolf |
|
{ 2,2 }, // Faith |
|
{ 71,0 }, // Bastille |
|
{ 3,5 }, // Crash |
|
{ 1,1 }, // Flynn |
|
{ 75,4 }, // Vegas |
|
}, |
|
{ |
|
{ 3, 14 }, // Sarge |
|
{ 3,10 }, // Jaeger |
|
{ 3,4 }, // Wildcat |
|
{ 0,0 }, // Wolf |
|
{ 2,0 }, // Faith |
|
{ 61,0 }, // Bastille |
|
{ 0,1 }, // Crash |
|
{ 3,0 }, // Flynn |
|
{ 61,0 }, // Vegas |
|
}, |
|
{ |
|
{ 3, 14 }, // Sarge |
|
{ 3,12 }, // Jaeger |
|
{ 3,5 }, // Wildcat |
|
{ 1,0 }, // Wolf |
|
{ 3,4 }, // Faith |
|
{ 123,11 }, // Bastille |
|
{ 1,3 }, // Crash |
|
{ 3,2 }, // Flynn |
|
{ 61,1 }, // Vegas |
|
}, |
|
{ |
|
{ 3, 16 }, // Sarge |
|
{ 3,13 }, // Jaeger |
|
{ 3,6 }, // Wildcat |
|
{ 1,3 }, // Wolf |
|
{ 3,7 }, // Faith |
|
{ 123,7 }, // Bastille |
|
{ 2,0 }, // Crash |
|
{ 1,1 }, // Flynn |
|
{ 61,2 }, // Vegas |
|
}, |
|
{ |
|
{ 3, 17 }, // Sarge |
|
{ 3,9 }, // Jaeger |
|
{ 0,0 }, // Wildcat |
|
{ 2,0 }, // Wolf |
|
{ 3,3 }, // Faith |
|
{ 83,0 }, // Bastille |
|
{ 3,3 }, // Crash |
|
{ 3,5 }, // Flynn |
|
{ 63,0 }, // Vegas |
|
}, |
|
{ |
|
{ 61, 1 }, // Sarge |
|
{ 3,7 }, // Jaeger |
|
{ 1,2 }, // Wildcat |
|
{ 3,1 }, // Wolf |
|
{ 3,8 }, // Faith |
|
{ 84,1 }, // Bastille |
|
{ 3,4 }, // Crash |
|
{ 3,3 }, // Flynn |
|
{ 112,1 }, // Vegas |
|
}, |
|
{ |
|
{ 61, 2 }, // Sarge |
|
{ 3,6 }, // Jaeger |
|
{ 45,1 }, // Wildcat |
|
{ 3,0 }, // Wolf |
|
{ 3,0 }, // Faith |
|
{ 87,0 }, // Bastille |
|
{ 27,2 }, // Crash |
|
{ 3,1 }, // Flynn |
|
{ 112,0 }, // Vegas |
|
}, |
|
{ |
|
{ 1, 1 }, // Sarge |
|
{ 3,2 }, // Jaeger |
|
{ 54,1 }, // Wildcat |
|
{ 3,2 }, // Wolf |
|
{ 3,9 }, // Faith |
|
{ 98,1 }, // Bastille |
|
{ 54,3 }, // Crash |
|
{ 5,3 }, // Flynn |
|
{ 88,0 }, // Vegas |
|
}, |
|
{ |
|
{ 1, 3 }, // Sarge |
|
{ 5,2 }, // Jaeger |
|
{ 61,0 }, // Wildcat |
|
{ 3,4 }, // Wolf |
|
{ 54,2 }, // Faith |
|
{ 99,0 }, // Bastille |
|
{ 72,4 }, // Crash |
|
{ 75,0 }, // Flynn |
|
{ 99,0 }, // Vegas |
|
}, |
|
{ |
|
{ 38, 2 }, // Sarge |
|
{ 54,3 }, // Jaeger |
|
{ 3,3 }, // Wildcat |
|
{ 3,5 }, // Wolf |
|
{ 54,3 }, // Faith |
|
{ 2,2 }, // Bastille |
|
{ 73,1 }, // Crash |
|
{ 61,0 }, // Flynn |
|
{ 102,0 }, // Vegas |
|
}, |
|
}; |
|
|
|
bool CASW_MarineSpeech::ClientRequestChatter(int iChatterType, int iSubChatter) |
|
{ |
|
CASW_Marine_Profile *pProfile = m_pMarine->GetMarineResource()->GetProfile(); |
|
if ( !pProfile ) |
|
{ |
|
return false; |
|
} |
|
|
|
if ( iChatterType == -1 ) |
|
{ |
|
int nRandomSpeech = RandomInt( 0, g_nNumFlavorSpeech - 1 ); |
|
iChatterType = g_MarineFlavorSpeech[ nRandomSpeech ][ pProfile->GetVoiceType() ].uchChatterType; |
|
iSubChatter = g_MarineFlavorSpeech[ nRandomSpeech ][ pProfile->GetVoiceType() ].uchSubChatter; |
|
} |
|
|
|
// todo: disallow some chatter types (misleading or annoying ones like onfire, infested, etc) |
|
if (iChatterType < 0 || iChatterType >= NUM_CHATTER_LINES) |
|
{ |
|
AssertMsg1( false, "Faulty chatter type %d\n", iChatterType ); |
|
return false; |
|
} |
|
|
|
if (!m_pMarine || !m_pMarine->GetMarineResource() || (m_pMarine->GetHealth()<=0 && iChatterType != CHATTER_DIE)) |
|
{ |
|
AssertMsg( false, "Absent marine tried to chatter\n" ); |
|
return false; |
|
} |
|
|
|
if (gpGlobals->curtime < GetTeamChatterTime()) |
|
{ |
|
return false; |
|
} |
|
|
|
//if (!TranslateChatter(iChatterType, pProfile)) |
|
//return false; |
|
|
|
// if marine doesn't have this line, then don't try playing it |
|
const char *szChatter = pProfile->m_Chatter[iChatterType]; |
|
if (szChatter[0] == '\0') |
|
{ |
|
return false; |
|
} |
|
|
|
InternalPlayChatter(m_pMarine, szChatter, ASW_CHATTER_TIMER_TEAM, iChatterType, iSubChatter); |
|
return true; |
|
} |
|
|
|
bool CASW_MarineSpeech::AllowCalmConversations(int iConversation) |
|
{ |
|
if (ASWGameRules() && ASWGameRules()->m_fLastFireTime > gpGlobals->curtime - ASW_CALM_CHATTER_TIME) |
|
return false; |
|
|
|
return true; |
|
} |