//========================================================= // IdleRespond // Respond to a previous question //========================================================= void CMTalkMonster :: IdleRespond( void ) { int pitch = GetVoicePitch(); // play response PlaySentence( m_szGrp[TLK_ANSWER], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE ); }
void CTalkMonster::PlaySentence( const char *pszSentence, float duration, float volume, float attenuation ) { if ( !pszSentence ) return; Talk ( duration ); CTalkMonster::g_talkWaitTime = gpGlobals->time + duration + 2.0; if ( pszSentence[0] == '!' ) EMIT_SOUND_DYN( this, CHAN_VOICE, pszSentence, volume, attenuation, 0, GetVoicePitch()); else g_Sentences.PlayRndSz( this, pszSentence, volume, attenuation, 0, GetVoicePitch() ); // If you say anything, don't greet the player - you may have already spoken to them SetBits(m_bitsSaid, bit_saidHelloPlayer); }
//========================================================= // IdleRespond // Respond to a previous question //========================================================= void CTalkMonster :: IdleRespond( void ) { //GetVoicePitch mutates the random number generator so removing the call changes behavior - Solokiller /*int pitch = */GetVoicePitch(); // play response PlaySentence( m_szGrp[TLK_ANSWER], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE ); }
//========================================================= // FIdleSpeak // ask question of nearby friend, or make statement //========================================================= int CSittingScientist :: FIdleSpeak ( void ) { // try to start a conversation, or make statement int pitch; if (!FOkToSpeak()) return FALSE; // set global min delay for next conversation CTalkMonster::g_talkWaitTime = gpGlobals->time + RANDOM_FLOAT(4.8, 5.2); pitch = GetVoicePitch(); // if there is a friend nearby to speak to, play sentence, set friend's response time, return // try to talk to any standing or sitting scientists nearby CBaseEntity *pentFriend = FindNearestFriend(FALSE); if (pentFriend && RANDOM_LONG(0,1)) { CTalkMonster *pTalkMonster = GetClassPtr((CTalkMonster *)pentFriend->pev); pTalkMonster->SetAnswerQuestion( this ); IdleHeadTurn(pentFriend->pev->origin); SENTENCEG_PlayRndSz( ENT(pev), m_szGrp[TLK_PQUESTION], 1.0, ATTN_IDLE, 0, pitch ); // set global min delay for next conversation CTalkMonster::g_talkWaitTime = gpGlobals->time + RANDOM_FLOAT(4.8, 5.2); return TRUE; } // otherwise, play an idle statement if (RANDOM_LONG(0,1)) { SENTENCEG_PlayRndSz( ENT(pev), m_szGrp[TLK_PIDLE], 1.0, ATTN_IDLE, 0, pitch ); // set global min delay for next conversation CTalkMonster::g_talkWaitTime = gpGlobals->time + RANDOM_FLOAT(4.8, 5.2); return TRUE; } // never spoke CTalkMonster::g_talkWaitTime = 0; return FALSE; }
//========================================================= // PainSound //========================================================= void CScientist :: PainSound ( void ) { if (gpGlobals->time < m_painTime ) return; m_painTime = gpGlobals->time + RANDOM_FLOAT(0.5, 0.75); if ( FClassnameIs(pev, "monster_rosenberg")) EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "rosenberg/ro_pain1.wav", 1, ATTN_NORM, 0, GetVoicePitch()); else { switch (RANDOM_LONG(0,4)) { case 0: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "scientist/sci_pain1.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break; case 1: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "scientist/sci_pain2.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break; case 2: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "scientist/sci_pain3.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break; case 3: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "scientist/sci_pain4.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break; case 4: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "scientist/sci_pain5.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break; } } }
//========================================================= // DeathSound //========================================================= void CHeadCrab :: DeathSound ( void ) { EMIT_SOUND_DYN( edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pDeathSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() ); }
void CHeadCrab :: StartTask ( Task_t *pTask ) { m_iTaskStatus = TASKSTATUS_RUNNING; switch ( pTask->iTask ) { case TASK_RANGE_ATTACK1: { EMIT_SOUND_DYN( edict(), CHAN_WEAPON, pAttackSounds[0], GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() ); m_IdealActivity = ACT_RANGE_ATTACK1; SetTouch ( LeapTouch ); break; } default: { CBaseMonster :: StartTask( pTask ); } } }
//========================================================= // LeapTouch - this is the headcrab's touch function when it // is in the air //========================================================= void CHeadCrab :: LeapTouch ( CBaseEntity *pOther ) { if ( !pOther->pev->takedamage ) { return; } if ( pOther->Classify() == Classify() ) { return; } // Don't hit if back on ground if ( !FBitSet( pev->flags, FL_ONGROUND ) ) { EMIT_SOUND_DYN( edict(), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pBiteSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() ); pOther->TakeDamage( pev, pev, GetDamageAmount(), DMG_SLASH ); } SetTouch( NULL ); }
//========================================================= // HandleAnimEvent - catches the monster-specific messages // that occur when tagged animation frames are played. //========================================================= void CHeadCrab :: HandleAnimEvent( MonsterEvent_t *pEvent ) { switch( pEvent->event ) { case HC_AE_JUMPATTACK: { ClearBits( pev->flags, FL_ONGROUND ); UTIL_SetOrigin (pev, pev->origin + Vector ( 0 , 0 , 1) );// take him off ground so engine doesn't instantly reset onground UTIL_MakeVectors ( pev->angles ); Vector vecJumpDir; if (m_hEnemy != NULL) { float gravity = g_psv_gravity->value; if (gravity <= 1) gravity = 1; // How fast does the headcrab need to travel to reach that height given gravity? float height = (m_hEnemy->pev->origin.z + m_hEnemy->pev->view_ofs.z - pev->origin.z); if (height < 16) height = 16; float speed = sqrt( 2 * gravity * height ); float time = speed / gravity; // Scale the sideways velocity to get there at the right time vecJumpDir = (m_hEnemy->pev->origin + m_hEnemy->pev->view_ofs - pev->origin); vecJumpDir = vecJumpDir * ( 1.0 / time ); // Speed to offset gravity at the desired height vecJumpDir.z = speed; // Don't jump too far/fast float distance = vecJumpDir.Length(); if (distance > 650) { vecJumpDir = vecJumpDir * ( 650.0 / distance ); } } else { // jump hop, don't care where vecJumpDir = Vector( gpGlobals->v_forward.x, gpGlobals->v_forward.y, gpGlobals->v_up.z ) * 350; } int iSound = RANDOM_LONG(0,2); if ( iSound != 0 ) EMIT_SOUND_DYN( edict(), CHAN_VOICE, pAttackSounds[iSound], GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() ); pev->velocity = vecJumpDir; m_flNextAttack = gpGlobals->time + 2; } break; default: CBaseMonster::HandleAnimEvent( pEvent ); break; } }
//========================================================= // AlertSound //========================================================= void CHeadCrab :: PainSound ( void ) { EMIT_SOUND_DYN( edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY_PAYNED_PAIN_MONSTER(pPainSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() ); }
//========================================================= // FIdleSpeak // ask question of nearby friend, or make statement //========================================================= bool CTalkMonster::FIdleSpeak() { // try to start a conversation, or make statement const char *szIdleGroup; const char *szQuestionGroup; float duration; if (!FOkToSpeak()) return false; // set idle groups based on pre/post disaster if ( GetSpawnFlags().Any( SF_MONSTER_PREDISASTER ) ) { szIdleGroup = m_szGrp[TLK_PIDLE]; szQuestionGroup = m_szGrp[TLK_PQUESTION]; // set global min delay for next conversation duration = RANDOM_FLOAT(4.8, 5.2); } else { szIdleGroup = m_szGrp[TLK_IDLE]; szQuestionGroup = m_szGrp[TLK_QUESTION]; // set global min delay for next conversation duration = RANDOM_FLOAT(2.8, 3.2); } /*int pitch = */GetVoicePitch(); // player using this entity is alive and wounded? CBaseEntity *pTarget = m_hTargetEnt; if ( pTarget != NULL ) { if ( pTarget->IsPlayer() ) { if ( pTarget->IsAlive() ) { m_hTalkTarget = m_hTargetEnt; if (!FBitSet(m_bitsSaid, bit_saidDamageHeavy) && (m_hTargetEnt->GetHealth() <= m_hTargetEnt->GetMaxHealth() / 8)) { //EMIT_SOUND_DYN( this, CHAN_VOICE, m_szGrp[TLK_PLHURT3], 1.0, ATTN_IDLE, 0, pitch); PlaySentence( m_szGrp[TLK_PLHURT3], duration, VOL_NORM, ATTN_IDLE ); SetBits(m_bitsSaid, bit_saidDamageHeavy); return true; } else if (!FBitSet(m_bitsSaid, bit_saidDamageMedium) && (m_hTargetEnt->GetHealth() <= m_hTargetEnt->GetMaxHealth() / 4)) { //EMIT_SOUND_DYN( this, CHAN_VOICE, m_szGrp[TLK_PLHURT2], 1.0, ATTN_IDLE, 0, pitch); PlaySentence( m_szGrp[TLK_PLHURT2], duration, VOL_NORM, ATTN_IDLE ); SetBits(m_bitsSaid, bit_saidDamageMedium); return true; } else if (!FBitSet(m_bitsSaid, bit_saidDamageLight) && (m_hTargetEnt->GetHealth() <= m_hTargetEnt->GetMaxHealth() / 2)) { //EMIT_SOUND_DYN( this, CHAN_VOICE, m_szGrp[TLK_PLHURT1], 1.0, ATTN_IDLE, 0, pitch); PlaySentence( m_szGrp[TLK_PLHURT1], duration, VOL_NORM, ATTN_IDLE ); SetBits(m_bitsSaid, bit_saidDamageLight); return true; } } else { //!!!KELLY - here's a cool spot to have the talkmonster talk about the dead player if we want. // "Oh dear, Gordon Freeman is dead!" -Scientist // "Damn, I can't do this without you." -Barney } } } { // if there is a friend nearby to speak to, play sentence, set friend's response time, return CBaseEntity *pFriend = FindNearestFriend( false ); if( pFriend && !( pFriend->IsMoving() ) && ( RANDOM_LONG( 0, 99 ) < 75 ) ) { PlaySentence( szQuestionGroup, duration, VOL_NORM, ATTN_IDLE ); //SENTENCEG_PlayRndSz( this, szQuestionGroup, 1.0, ATTN_IDLE, 0, pitch ); // force friend to answer CTalkMonster *pTalkMonster = ( CTalkMonster * ) pFriend; m_hTalkTarget = pFriend; pTalkMonster->SetAnswerQuestion( this ); // UNDONE: This is EVIL!!! pTalkMonster->m_flStopTalkTime = m_flStopTalkTime; m_nSpeak++; return true; } } // otherwise, play an idle statement, try to face client when making a statement. if ( RANDOM_LONG(0,1) ) { //SENTENCEG_PlayRndSz( this, szIdleGroup, 1.0, ATTN_IDLE, 0, pitch ); CBaseEntity *pFriend = FindNearestFriend(true); if ( pFriend ) { m_hTalkTarget = pFriend; PlaySentence( szIdleGroup, duration, VOL_NORM, ATTN_IDLE ); m_nSpeak++; return true; } } // didn't speak Talk( 0 ); CTalkMonster::g_talkWaitTime = 0; return false; }
int CAI_Expresser::SpeakRawSentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, CBaseEntity *pListener ) { int sentenceIndex = -1; if ( !pszSentence ) return sentenceIndex; if ( pszSentence[0] == AI_SP_SPECIFIC_SENTENCE ) { sentenceIndex = SENTENCEG_Lookup( pszSentence ); if( sentenceIndex == -1 ) { // sentence not found return -1; } CPASAttenuationFilter filter( GetOuter(), soundlevel ); CBaseEntity::EmitSentenceByIndex( filter, GetOuter()->entindex(), CHAN_VOICE, sentenceIndex, volume, soundlevel, 0, GetVoicePitch()); } else { sentenceIndex = SENTENCEG_PlayRndSz( GetOuter()->NetworkProp()->edict(), pszSentence, volume, soundlevel, 0, GetVoicePitch() ); } SpeechMsg( GetOuter(), "SpeakRawSentence( %s, %f) %f\n", pszSentence, delay, engine->SentenceLength( sentenceIndex ) ); NoteSpeaking( engine->SentenceLength( sentenceIndex ), delay ); return sentenceIndex; }
//========================================================= // DeathSound //========================================================= void CBarney :: DeathSound ( void ) { switch (RANDOM_LONG(0,2)) { case 0: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_die1.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break; case 1: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_die2.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break; case 2: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_die3.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break; } }
//========================================================= // PainSound //========================================================= void CBarney :: PainSound ( void ) { if (gpGlobals->time < m_painTime) return; m_painTime = gpGlobals->time + RANDOM_FLOAT(0.5, 0.75); switch (RANDOM_LONG(0,2)) { case 0: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_pain1.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break; case 1: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_pain2.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break; case 2: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_pain3.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break; } }
void CNPC_Headcrab::AttackSound( void ) { CPASAttenuationFilter filter( this, ATTN_IDLE ); enginesound->EmitSound( filter, entindex(), CHAN_VOICE, RANDOM_SOUND_ARRAY( pAttackSounds ), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() ); }