/* Callback for JVMTI_EVENT_VM_DEATH */ static void JNICALL cbVMDeath(jvmtiEnv *jvmti, JNIEnv *env) { enter_critical_section(jvmti); { jclass klass; jfieldID field; /* The VM has died. */ stdout_message("VMDeath\n"); /* Disengage calls in MTRACE_class. */ klass = (*env)->FindClass(env, STRING(MTRACE_class)); if ( klass == NULL ) { fatal_error("ERROR: JNI: Cannot find %s with FindClass\n", STRING(MTRACE_class)); } field = (*env)->GetStaticFieldID(env, klass, STRING(MTRACE_engaged), "I"); if ( field == NULL ) { fatal_error("ERROR: JNI: Cannot get field from %s\n", STRING(MTRACE_class)); } (*env)->SetStaticIntField(env, klass, field, 0); /* The critical section here is important to hold back the VM death * until all other callbacks have completed. */ /* Since this critical section could be holding up other threads * in other event callbacks, we need to indicate that the VM is * dead so that the other callbacks can short circuit their work. * We don't expect any further events after VmDeath but we do need * to be careful that existing threads might be in our own agent * callback code. */ gdata->vm_is_dead = JNI_TRUE; /* Dump out stats */ stdout_message("Begin Class Stats\n"); if ( gdata->ccount > 0 ) { int cnum; /* Sort table (in place) by number of method calls into class. */ /* Note: Do not use this table after this qsort! */ qsort(gdata->classes, gdata->ccount, sizeof(ClassInfo), &class_compar); /* Dump out gdata->max_count most called classes */ for ( cnum=gdata->ccount-1 ; cnum >= 0 && cnum >= gdata->ccount - gdata->max_count; cnum-- ) { ClassInfo *cp; int mnum; cp = gdata->classes + cnum; stdout_message("Class %s %d calls\n", cp->name, cp->calls); if ( cp->calls==0 ) continue; /* Sort method table (in place) by number of method calls. */ /* Note: Do not use this table after this qsort! */ qsort(cp->methods, cp->mcount, sizeof(MethodInfo), &method_compar); for ( mnum=cp->mcount-1 ; mnum >= 0 ; mnum-- ) { MethodInfo *mp; mp = cp->methods + mnum; if ( mp->calls==0 ) continue; stdout_message("\tMethod %s %s %d calls %d returns\n", mp->name, mp->signature, mp->calls, mp->returns); } } } stdout_message("End Class Stats\n"); (void)fflush(stdout); } exit_critical_section(jvmti); }
//------------------------------------------------------------------------------ // Purpose: //------------------------------------------------------------------------------ void CAmbientGeneric::Activate( void ) { BaseClass::Activate(); // Initialize sound source. If no source was given, or source can't be found // then this is the source if (m_hSoundSource == NULL) { if (m_sSourceEntName != NULL_STRING) { m_hSoundSource = gEntList.FindEntityByName( NULL, m_sSourceEntName ); if ( m_hSoundSource != NULL ) { m_nSoundSourceEntIndex = m_hSoundSource->entindex(); } } if (m_hSoundSource == NULL) { m_hSoundSource = this; m_nSoundSourceEntIndex = entindex(); } else { if ( !FBitSet( m_spawnflags, SF_AMBIENT_SOUND_EVERYWHERE ) ) { AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); } } } #ifdef PORTAL // This is the only way we can silence the radio sound from the first room without touching them map -- jdw if ( PortalGameRules() && PortalGameRules()->ShouldRemoveRadio() ) { if ( V_strcmp( STRING( gpGlobals->mapname ), "testchmb_a_00" ) == 0 || V_strcmp( STRING( gpGlobals->mapname ), "testchmb_a_11" ) == 0 || V_strcmp( STRING( gpGlobals->mapname ), "testchmb_a_14" ) == 0 ) { if ( V_strcmp( STRING( GetEntityName() ), "radio_sound" ) == 0 ) { UTIL_Remove( this ); return; } } } #endif // PORTAL // If active start the sound if ( m_fActive ) { int flags = SND_SPAWNING; // If we are loading a saved game, we can't write into the init/signon buffer here, so just issue // as a regular sound message... if ( gpGlobals->eLoadType == MapLoad_Transition || gpGlobals->eLoadType == MapLoad_LoadGame || g_pGameRules->InRoundRestart() ) { flags = SND_NOFLAGS; } // Tracker 76119: 8/12/07 ywb: // Make sure pitch and volume are set up to the correct value (especially after restoring a .sav file) flags |= ( SND_CHANGE_PITCH | SND_CHANGE_VOL ); // Don't bother sending over to client if volume is zero, though if ( m_dpv.vol > 0 ) { SendSound( (SoundFlags_t)flags ); } SetNextThink( gpGlobals->curtime + 0.1f ); } }
entityIndex = (short)trace.m_pEnt ? trace.m_pEnt->entindex() : 0; if ( entityIndex ) { CBaseEntity *ent = trace.m_pEnt; if ( ent ) { modelIndex = ent->GetModelIndex(); VectorITransform( GetAbsOrigin(), ent->EntityToWorldTransform(), position ); canDraw = ( modelIndex != 0 ); if ( !canDraw ) { Warning( "Suppressed StaticDecal which would have hit entity %i (class:%s, name:%s) with modelindex = 0\n", ent->entindex(), ent->GetClassname(), STRING( ent->GetEntityName() ) ); } } } if ( canDraw ) { engine->StaticDecal( position, m_nTexture, entityIndex, modelIndex, m_bLowPriority ); } SUB_Remove(); } bool CDecal::KeyValue( const char *szKeyName, const char *szValue ) {
void CWorld :: Precache( void ) { g_pLastSpawn = NULL; #if 1 CVAR_SET_STRING("sv_gravity", "800"); // 67ft/sec CVAR_SET_STRING("sv_stepsize", "18"); #else CVAR_SET_STRING("sv_gravity", "384"); // 32ft/sec CVAR_SET_STRING("sv_stepsize", "24"); #endif CVAR_SET_STRING("room_type", "0");// clear DSP // QUAKECLASSIC // Set various physics cvars to Quake's values CVAR_SET_STRING("sv_friction", "4"); CVAR_SET_STRING("sv_maxspeed", "400"); CVAR_SET_STRING("sv_airaccelerate", "0.7"); // Set up game rules if (g_pGameRules) { delete g_pGameRules; } g_pGameRules = InstallGameRules( ); //!!!UNDONE why is there so much Spawn code in the Precache function? I'll just keep it here InitBodyQue(); // init sentence group playback stuff from sentences.txt. // ok to call this multiple times, calls after first are ignored. SENTENCEG_Init(); // init texture type array from materials.txt TEXTURETYPE_Init(); // the area based ambient sounds MUST be the first precache_sounds // player precaches W_Precache (); // get weapon precaches ClientPrecache(); // QUAKECLASSIC QuakeClassicPrecache(); // sounds used from C physics code PRECACHE_SOUND("common/null.wav"); // clears sound channels PRECACHE_SOUND( "items/suitchargeok1.wav" );//!!! temporary sound for respawning weapons. PRECACHE_SOUND( "items/gunpickup2.wav" );// player picks up a gun. PRECACHE_SOUND( "common/bodydrop3.wav" );// dead bodies hitting the ground (animation events) PRECACHE_SOUND( "common/bodydrop4.wav" ); g_Language = (int)CVAR_GET_FLOAT( "sv_language" ); if ( g_Language == LANGUAGE_GERMAN ) { PRECACHE_MODEL( "models/germangibs.mdl" ); } else { PRECACHE_MODEL( "models/hgibs.mdl" ); PRECACHE_MODEL( "models/agibs.mdl" ); } PRECACHE_SOUND ("weapons/ric1.wav"); PRECACHE_SOUND ("weapons/ric2.wav"); PRECACHE_SOUND ("weapons/ric3.wav"); PRECACHE_SOUND ("weapons/ric4.wav"); PRECACHE_SOUND ("weapons/ric5.wav"); // // Setup light animation tables. 'a' is total darkness, 'z' is maxbright. // // 0 normal LIGHT_STYLE(0, "m"); // 1 FLICKER (first variety) LIGHT_STYLE(1, "mmnmmommommnonmmonqnmmo"); // 2 SLOW STRONG PULSE LIGHT_STYLE(2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba"); // 3 CANDLE (first variety) LIGHT_STYLE(3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg"); // 4 FAST STROBE LIGHT_STYLE(4, "mamamamamama"); // 5 GENTLE PULSE 1 LIGHT_STYLE(5,"jklmnopqrstuvwxyzyxwvutsrqponmlkj"); // 6 FLICKER (second variety) LIGHT_STYLE(6, "nmonqnmomnmomomno"); // 7 CANDLE (second variety) LIGHT_STYLE(7, "mmmaaaabcdefgmmmmaaaammmaamm"); // 8 CANDLE (third variety) LIGHT_STYLE(8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa"); // 9 SLOW STROBE (fourth variety) LIGHT_STYLE(9, "aaaaaaaazzzzzzzz"); // 10 FLUORESCENT FLICKER LIGHT_STYLE(10, "mmamammmmammamamaaamammma"); // 11 SLOW PULSE NOT FADE TO BLACK LIGHT_STYLE(11, "abcdefghijklmnopqrrqponmlkjihgfedcba"); // 12 UNDERWATER LIGHT MUTATION // this light only distorts the lightmap - no contribution // is made to the brightness of affected surfaces LIGHT_STYLE(12, "mmnnmmnnnmmnn"); // styles 32-62 are assigned by the light program for switchable lights // 63 testing LIGHT_STYLE(63, "a"); for ( int i = 0; i < ARRAYSIZE(gDecals); i++ ) gDecals[i].index = DECAL_INDEX( gDecals[i].name ); // init the WorldGraph. WorldGraph.InitGraph(); // make sure the .NOD file is newer than the .BSP file. if ( !WorldGraph.CheckNODFile ( ( char * )STRING( gpGlobals->mapname ) ) ) {// NOD file is not present, or is older than the BSP file. WorldGraph.AllocNodes (); } else {// Load the node graph for this level if ( !WorldGraph.FLoadGraph ( (char *)STRING( gpGlobals->mapname ) ) ) {// couldn't load, so alloc and prepare to build a graph. ALERT ( at_console, "*Error opening .NOD file\n" ); WorldGraph.AllocNodes (); } else { ALERT ( at_console, "\n*Graph Loaded!\n" ); } } if ( pev->speed > 0 ) CVAR_SET_FLOAT( "sv_zmax", pev->speed ); else CVAR_SET_FLOAT( "sv_zmax", 4096 ); // QUAKECLASSIC: No Fades /* if ( pev->netname ) { ALERT( at_aiconsole, "Chapter title: %s\n", STRING(pev->netname) ); CBaseEntity *pEntity = CBaseEntity::Create( "env_message", g_vecZero, g_vecZero, NULL ); if ( pEntity ) { pEntity->SetThink( SUB_CallUseToggle ); pEntity->pev->message = pev->netname; pev->netname = 0; pEntity->pev->nextthink = gpGlobals->time + 0.3; pEntity->pev->spawnflags = SF_MESSAGE_ONCE; } } */ // QUAKECLASSIC: No Darkness /* if ( pev->spawnflags & SF_WORLD_DARK ) CVAR_SET_FLOAT( "v_dark", 1.0 ); else CVAR_SET_FLOAT( "v_dark", 0.0 ); */ if ( pev->spawnflags & SF_WORLD_TITLE ) gDisplayTitle = TRUE; // display the game title if this key is set else gDisplayTitle = FALSE; if ( pev->spawnflags & SF_WORLD_FORCETEAM ) { CVAR_SET_FLOAT( "mp_defaultteam", 1 ); } else { CVAR_SET_FLOAT( "mp_defaultteam", 0 ); } }
//----------------------------------------------------------------------------- // Purpose: Fill out a prop's with base data parsed from the propdata file //----------------------------------------------------------------------------- int CPropData::ParsePropFromBase( CBaseEntity *pProp, const char *pszPropData ) { if ( !m_bPropDataLoaded ) return PARSE_FAILED_NO_DATA; IBreakableWithPropData *pBreakableInterface = dynamic_cast<IBreakableWithPropData*>(pProp); if ( !pBreakableInterface ) { return PARSE_FAILED_BAD_DATA; } if ( !m_pKVPropData ) { return PARSE_FAILED_BAD_DATA; } // Find the specified propdata KeyValues *pSection = m_pKVPropData->FindKey( pszPropData ); if ( !pSection ) { Warning("%s '%s' has a base specified as '%s', but there is no matching entry in propdata.txt.\n", pProp->GetClassname(), STRING( pProp->GetModelName() ), pszPropData ); return PARSE_FAILED_BAD_DATA; } // Store off the first base data for debugging if ( pBreakableInterface->GetBasePropData() == NULL_STRING ) { pBreakableInterface->SetBasePropData( AllocPooledString( pszPropData ) ); } return ParsePropFromKV( pProp, pSection, pSection ); }
//----------------------------------------------------------------------------- // Purpose: play door or button locked or unlocked sounds. // NOTE: this routine is shared by doors and buttons // Input : pEdict - // pls - // flocked - if true, play 'door is locked' sound, otherwise play 'door // is unlocked' sound. // fbutton - //----------------------------------------------------------------------------- void PlayLockSounds(CBaseEntity *pEdict, locksound_t *pls, int flocked, int fbutton) { if ( pEdict->HasSpawnFlags( SF_DOOR_SILENT ) ) { return; } float flsoundwait = ( fbutton ) ? BUTTON_SOUNDWAIT : DOOR_SOUNDWAIT; if ( flocked ) { int fplaysound = (pls->sLockedSound != NULL_STRING && gpGlobals->curtime > pls->flwaitSound); int fplaysentence = (pls->sLockedSentence != NULL_STRING && !pls->bEOFLocked && gpGlobals->curtime > pls->flwaitSentence); float fvol = ( fplaysound && fplaysentence ) ? 0.25f : 1.0f; // if there is a locked sound, and we've debounced, play sound if (fplaysound) { // play 'door locked' sound CPASAttenuationFilter filter( pEdict ); EmitSound_t ep; ep.m_nChannel = CHAN_ITEM; ep.m_pSoundName = (char*)STRING(pls->sLockedSound); ep.m_flVolume = fvol; ep.m_SoundLevel = SNDLVL_NORM; CBaseEntity::EmitSound( filter, pEdict->entindex(), ep ); pls->flwaitSound = gpGlobals->curtime + flsoundwait; } // if there is a sentence, we've not played all in list, and we've debounced, play sound if (fplaysentence) { // play next 'door locked' sentence in group int iprev = pls->iLockedSentence; pls->iLockedSentence = SENTENCEG_PlaySequentialSz( pEdict->edict(), STRING(pls->sLockedSentence), 0.85f, SNDLVL_NORM, 0, 100, pls->iLockedSentence, FALSE); pls->iUnlockedSentence = 0; // make sure we don't keep calling last sentence in list pls->bEOFLocked = (iprev == pls->iLockedSentence); pls->flwaitSentence = gpGlobals->curtime + DOOR_SENTENCEWAIT; } } else { // UNLOCKED SOUND int fplaysound = (pls->sUnlockedSound != NULL_STRING && gpGlobals->curtime > pls->flwaitSound); int fplaysentence = (pls->sUnlockedSentence != NULL_STRING && !pls->bEOFUnlocked && gpGlobals->curtime > pls->flwaitSentence); float fvol; // if playing both sentence and sound, lower sound volume so we hear sentence fvol = ( fplaysound && fplaysentence ) ? 0.25f : 1.0f; // play 'door unlocked' sound if set if (fplaysound) { CPASAttenuationFilter filter( pEdict ); EmitSound_t ep; ep.m_nChannel = CHAN_ITEM; ep.m_pSoundName = (char*)STRING(pls->sUnlockedSound); ep.m_flVolume = fvol; ep.m_SoundLevel = SNDLVL_NORM; CBaseEntity::EmitSound( filter, pEdict->entindex(), ep ); pls->flwaitSound = gpGlobals->curtime + flsoundwait; } // play next 'door unlocked' sentence in group if (fplaysentence) { int iprev = pls->iUnlockedSentence; pls->iUnlockedSentence = SENTENCEG_PlaySequentialSz(pEdict->edict(), STRING(pls->sUnlockedSentence), 0.85, SNDLVL_NORM, 0, 100, pls->iUnlockedSentence, FALSE); pls->iLockedSentence = 0; // make sure we don't keep calling last sentence in list pls->bEOFUnlocked = (iprev == pls->iUnlockedSentence); pls->flwaitSentence = gpGlobals->curtime + DOOR_SENTENCEWAIT; } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CBaseDoor::Precache( void ) { //Fill in a default value if necessary if ( IsRotatingDoor() ) { UTIL_ValidateSoundName( m_NoiseMoving, "RotDoorSound.DefaultMove" ); UTIL_ValidateSoundName( m_NoiseArrived, "RotDoorSound.DefaultArrive" ); UTIL_ValidateSoundName( m_ls.sLockedSound, "RotDoorSound.DefaultLocked" ); UTIL_ValidateSoundName( m_ls.sUnlockedSound,"DoorSound.Null" ); } else { UTIL_ValidateSoundName( m_NoiseMoving, "DoorSound.DefaultMove" ); UTIL_ValidateSoundName( m_NoiseArrived, "DoorSound.DefaultArrive" ); #ifndef HL1_DLL UTIL_ValidateSoundName( m_ls.sLockedSound, "DoorSound.DefaultLocked" ); #endif UTIL_ValidateSoundName( m_ls.sUnlockedSound,"DoorSound.Null" ); } #ifdef HL1_DLL if( m_ls.sLockedSound != NULL_STRING && strlen((char*)STRING(m_ls.sLockedSound)) < 4 ) { // Too short to be ANYTHING ".wav", so it must be an old index into a long-lost // array of sound choices. slam it to a known "deny" sound. We lose the designer's // original selection, but we don't get unresponsive doors. m_ls.sLockedSound = AllocPooledString("buttons/button2.wav"); } #endif//HL1_DLL //Precache them all PrecacheScriptSound( (char *) STRING(m_NoiseMoving) ); PrecacheScriptSound( (char *) STRING(m_NoiseArrived) ); PrecacheScriptSound( (char *) STRING(m_NoiseMovingClosed) ); PrecacheScriptSound( (char *) STRING(m_NoiseArrivedClosed) ); PrecacheScriptSound( (char *) STRING(m_ls.sLockedSound) ); PrecacheScriptSound( (char *) STRING(m_ls.sUnlockedSound) ); //Get sentence group names, for doors which are directly 'touched' to open switch (m_bLockedSentence) { case 1: m_ls.sLockedSentence = AllocPooledString("NA"); break; // access denied case 2: m_ls.sLockedSentence = AllocPooledString("ND"); break; // security lockout case 3: m_ls.sLockedSentence = AllocPooledString("NF"); break; // blast door case 4: m_ls.sLockedSentence = AllocPooledString("NFIRE"); break; // fire door case 5: m_ls.sLockedSentence = AllocPooledString("NCHEM"); break; // chemical door case 6: m_ls.sLockedSentence = AllocPooledString("NRAD"); break; // radiation door case 7: m_ls.sLockedSentence = AllocPooledString("NCON"); break; // gen containment case 8: m_ls.sLockedSentence = AllocPooledString("NH"); break; // maintenance door case 9: m_ls.sLockedSentence = AllocPooledString("NG"); break; // broken door default: m_ls.sLockedSentence = NULL_STRING; break; } switch (m_bUnlockedSentence) { case 1: m_ls.sUnlockedSentence = AllocPooledString("EA"); break; // access granted case 2: m_ls.sUnlockedSentence = AllocPooledString("ED"); break; // security door case 3: m_ls.sUnlockedSentence = AllocPooledString("EF"); break; // blast door case 4: m_ls.sUnlockedSentence = AllocPooledString("EFIRE"); break; // fire door case 5: m_ls.sUnlockedSentence = AllocPooledString("ECHEM"); break; // chemical door case 6: m_ls.sUnlockedSentence = AllocPooledString("ERAD"); break; // radiation door case 7: m_ls.sUnlockedSentence = AllocPooledString("ECON"); break; // gen containment case 8: m_ls.sUnlockedSentence = AllocPooledString("EH"); break; // maintenance door default: m_ls.sUnlockedSentence = NULL_STRING; break; } }
void CBaseEntity::SUB_UseTargets(CBaseEntity *pActivator, USE_TYPE useType, float value) { if (!FStringNull(pev->target)) FireTargets(STRING(pev->target), pActivator, this, useType, value); }
const char *variant_t::ToString( void ) const { COMPILE_TIME_ASSERT( sizeof(string_t) == sizeof(int) ); static char szBuf[512]; switch (fieldType) { case FIELD_STRING: { return(STRING(iszVal)); } case FIELD_BOOLEAN: { if (bVal == 0) { Q_strncpy(szBuf, "false",sizeof(szBuf)); } else { Q_strncpy(szBuf, "true",sizeof(szBuf)); } return(szBuf); } case FIELD_INTEGER: { Q_snprintf( szBuf, sizeof( szBuf ), "%i", iVal ); return(szBuf); } case FIELD_FLOAT: { Q_snprintf(szBuf,sizeof(szBuf), "%g", flVal); return(szBuf); } case FIELD_COLOR32: { Q_snprintf(szBuf,sizeof(szBuf), "%d %d %d %d", (int)rgbaVal.r, (int)rgbaVal.g, (int)rgbaVal.b, (int)rgbaVal.a); return(szBuf); } case FIELD_VECTOR: { Q_snprintf(szBuf,sizeof(szBuf), "[%g %g %g]", (double)vecVal[0], (double)vecVal[1], (double)vecVal[2]); return(szBuf); } case FIELD_VOID: { szBuf[0] = '\0'; return(szBuf); } case FIELD_EHANDLE: { const char *pszName = (Entity()) ? STRING(Entity()->GetEntityName()) : "<<null entity>>"; Q_strncpy( szBuf, pszName, 512 ); return (szBuf); } } return("No conversion to string"); }
//----------------------------------------------------------------------------- // Purpose: Hook for the sound system to tell us when a sound's been played //----------------------------------------------------------------------------- MicrophoneResult_t CEnvMicrophone::SoundPlayed( int entindex, const char *soundname, soundlevel_t soundlevel, float flVolume, int iFlags, int iPitch, const Vector *pOrigin, float soundtime, CUtlVector< Vector >& soundorigins ) { if ( m_bAvoidFeedback ) return MicrophoneResult_Ok; // Don't hear sounds that have already been heard by a microphone to avoid feedback! if ( iFlags & SND_SPEAKER ) return MicrophoneResult_Ok; #ifdef DEBUG_MICROPHONE Msg("%s heard %s: ", STRING(GetEntityName()), soundname ); #endif if ( !CanHearSound( entindex, soundlevel, flVolume, pOrigin ) ) return MicrophoneResult_Ok; // We've heard it. Play it out our speaker. If our speaker's gone away, we're done. if ( !m_hSpeaker ) { // First time, find our speaker. Done here, because finding it in Activate() wouldn't // find players, and we need to be able to specify !player for a speaker. if ( m_iszSpeakerName != NULL_STRING ) { m_hSpeaker = gEntList.FindEntityByName(NULL, STRING(m_iszSpeakerName) ); if ( !m_hSpeaker ) { Warning( "EnvMicrophone %s specifies a non-existent speaker name: %s\n", STRING(GetEntityName()), STRING(m_iszSpeakerName) ); m_iszSpeakerName = NULL_STRING; } } if ( !m_hSpeaker ) { return MicrophoneResult_Remove; } } m_bAvoidFeedback = true; // Add the speaker flag. Detected at playback and applies the speaker filter. iFlags |= SND_SPEAKER; CPASAttenuationFilter filter( m_hSpeaker ); EmitSound_t ep; ep.m_nChannel = CHAN_STATIC; ep.m_pSoundName = soundname; ep.m_flVolume = flVolume; ep.m_SoundLevel = soundlevel; ep.m_nFlags = iFlags; ep.m_nPitch = iPitch; ep.m_pOrigin = &m_hSpeaker->GetAbsOrigin(); ep.m_flSoundTime = soundtime; ep.m_nSpeakerEntity = entindex; CBaseEntity::EmitSound( filter, m_hSpeaker->entindex(), ep ); Q_strncpy( m_szLastSound, soundname, sizeof(m_szLastSound) ); m_OnRoutedSound.FireOutput( this, this, 0 ); m_bAvoidFeedback = false; // Copy emitted origin to soundorigins array for ( int i = 0; i < ep.m_UtlVecSoundOrigin.Count(); ++i ) { soundorigins.AddToTail( ep.m_UtlVecSoundOrigin[ i ] ); } // Do we want to allow the original sound to play? if ( m_spawnflags & SF_MICROPHONE_SWALLOW_ROUTED_SOUNDS ) { return MicrophoneResult_Swallow; } return MicrophoneResult_Ok; }
void ListLoader::startTag(const string& name, StringPairList& attribs, bool simple) { #ifdef _DEBUG static size_t g_max_attribs_size = 0; if (g_max_attribs_size != attribs.size()) { g_max_attribs_size = attribs.size(); // dcdebug("ListLoader::startTag g_max_attribs_size = %d , attribs.capacity() = %d\n", g_max_attribs_size, attribs.capacity()); } #endif if (ClientManager::isBeforeShutdown()) { throw AbortException("ListLoader::startTag - ClientManager::isBeforeShutdown()"); } if (m_list->getAbort()) { throw AbortException("ListLoader::startTag - " + STRING(ABORT_EM)); } if (m_is_in_listing) { if (name == g_SFile) { dcassert(attribs.size() >= 3); // Иногда есть Shared - 4-тый атрибут. // это тэг от грея. его тоже можно обработать и записать в TS. хотя там 64 битное время const string& l_name = getAttrib(attribs, g_SName, 0); if (l_name.empty()) { dcassert(0); return; } const string& l_s = getAttrib(attribs, g_SSize, 1); if (l_s.empty()) { dcassert(0); return; } const auto l_size = Util::toInt64(l_s); const string& l_h = getAttrib(attribs, g_STTH, 2); if (l_h.empty() || (m_is_own_list == false && l_h.compare(0, 39, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 39) == 0)) { //dcassert(0); return; } const TTHValue l_tth(l_h); /// @todo verify validity? dcassert(l_tth != TTHValue()); if (m_is_updating) { // just update the current file if it is already there. for (auto i = m_cur->m_files.cbegin(); i != m_cur->m_files.cend(); ++i) { auto& file = **i; /// @todo comparisons should be case-insensitive but it takes too long - add a cache if (file.getName() == l_name || file.getTTH() == l_tth) { file.setName(l_name); file.setSize(l_size); file.setTTH(l_tth); return; } } } // [+] FlylinkDC std::shared_ptr<CFlyMediaInfo> l_mediaXY; uint32_t l_i_ts = 0; int l_i_hit = 0; string l_hit; #ifdef FLYLINKDC_USE_DIRLIST_FILE_EXT_STAT auto& l_item = DirectoryListing::g_ext_stat[Util::getFileExtWithoutDot(Text::toLower(l_name))]; l_item.m_count++; if (l_size > l_item.m_max_size) l_item.m_max_size = l_size; if (l_size < l_item.m_min_size) l_item.m_min_size = l_size; #endif if (attribs.size() >= 4) // 3 - стандартный DC++, 4 - GreyLinkDC++ { if (attribs.size() == 4 || attribs.size() >= 11) // Хитрый расширенный формат от http://p2p.toom.su/fs/hms/FCYECUWQ7F5A2FABW32UTMCT6MEMI3GPXBZDQCQ/) { const string l_sharedGL = getAttrib(attribs, g_SShared, 4); if (!l_sharedGL.empty()) { const int64_t tmp_ts = _atoi64(l_sharedGL.c_str()) - 116444736000000000L ; if (tmp_ts <= 0L) l_i_ts = 0; else l_i_ts = uint32_t(tmp_ts / 10000000L); } } string l_ts; if (l_i_ts == 0) { l_ts = getAttrib(attribs, g_STS, 3); // TODO проверить attribs.size() >= 4 если = 4 или 3 то TS нет и можно не искать } if (!m_is_first_check_mediainfo_list) { m_is_first_check_mediainfo_list = true; m_is_mediainfo_list = !l_ts.empty(); } if (!l_ts.empty() // Extended tags - exists only FlylinkDC++ or StrongDC++ sqlite or clones || l_i_ts // Грейлинк - время расшаривания ) { if (!l_ts.empty()) { l_i_ts = atoi(l_ts.c_str()); } if (attribs.size() > 4) // TODO - собрать комбинации всех случаев { l_hit = getAttrib(attribs, g_SHit, 3); const std::string& l_audio = getAttrib(attribs, g_SMAudio, 3); const std::string& l_video = getAttrib(attribs, g_SMVideo, 3); if (!l_audio.empty() || !l_video.empty()) { const string& l_br = getAttrib(attribs, g_SBR, 4); l_mediaXY = std::make_shared<CFlyMediaInfo>(getAttrib(attribs, g_SWH, 3), atoi(l_br.c_str()), l_audio, l_video ); } } #if 0 if (attribs.size() > 4) // TODO - собрать комбинации всех случаев { CFlyMediainfoRAW l_media_item; { l_media_item.m_audio = getAttrib(attribs, g_SMAudio, 3); const size_t l_pos = l_media_item.m_audio.find('|', 0); if (l_pos != string::npos && l_pos) { if (l_pos + 2 < l_media_item.m_audio.length()) { l_media_item.m_audio = l_media_item.m_audio.substr(l_pos + 2); } } } l_media_item.m_video = getAttrib(attribs, g_SMVideo, 3); l_hit = getAttrib(attribs, g_SHit, 3); l_media_item.m_WH = getAttrib(attribs, g_SWH, 3); if (!l_media_item.m_audio.empty() || !l_media_item.m_video.empty()) { l_media_item.m_br = getAttrib(attribs, g_SBR, 4); auto& l_find_mi = g_cache_mediainfo[l_media_item]; if (!l_find_mi) { l_find_mi = std::make_shared<CFlyMediaInfo>(l_media_item.m_WH, atoi(l_media_item.m_br.c_str()), l_media_item.m_audio, l_media_item.m_video ); l_mediaXY = l_find_mi; } } } #endif } l_i_hit = l_hit.empty() ? 0 : atoi(l_hit.c_str()); } auto f = new DirectoryListing::File(m_cur, l_name, l_size, l_tth, l_i_hit, l_i_ts, l_mediaXY); m_cur->m_virus_detect.add(l_name, l_size); m_cur->m_files.push_back(f); if (l_size) { if (m_is_own_list)//[+] FlylinkDC++ { f->setFlag(DirectoryListing::FLAG_SHARED_OWN); // TODO - убить FLAG_SHARED_OWN } else { if (ShareManager::isTTHShared(f->getTTH())) { f->setFlag(DirectoryListing::FLAG_SHARED); } else { if (QueueManager::is_queue_tth(f->getTTH())) { f->setFlag(DirectoryListing::FLAG_QUEUE); } // TODO if(l_size >= 100 * 1024 *1024) { if (!CFlyServerConfig::isParasitFile(f->getName())) // TODO - опимизнуть по расширениям { f->setFlag(DirectoryListing::FLAG_NOT_SHARED); const auto l_status_file = CFlylinkDBManager::getInstance()->get_status_file(f->getTTH()); // TODO - унести в отдельную нитку? if (l_status_file & CFlylinkDBManager::PREVIOUSLY_DOWNLOADED) f->setFlag(DirectoryListing::FLAG_DOWNLOAD); if (l_status_file & CFlylinkDBManager::VIRUS_FILE_KNOWN) f->setFlag(DirectoryListing::FLAG_VIRUS_FILE); if (l_status_file & CFlylinkDBManager::PREVIOUSLY_BEEN_IN_SHARE) f->setFlag(DirectoryListing::FLAG_OLD_TTH); } } } }//[+] FlylinkDC++ } } else if (name == g_SDirectory) { string l_file_name = getAttrib(attribs, g_SName, 0); if (l_file_name.empty()) { // throw SimpleXMLException("Directory missing name attribute"); l_file_name = "empty_file_name_" + Util::toString(++m_empty_file_name_counter); } const bool incomp = getAttrib(attribs, sIncomplete, 1) == "1"; DirectoryListing::Directory* d = nullptr; if (m_is_updating) { for (auto i = m_cur->directories.cbegin(); i != m_cur->directories.cend(); ++i) { /// @todo comparisons should be case-insensitive but it takes too long - add a cache if ((*i)->getName() == l_file_name) { d = *i; if (!d->getComplete()) { d->setComplete(!incomp); } break; } } } if (d == nullptr) { d = new DirectoryListing::Directory(m_list, m_cur, l_file_name, false, !incomp, isMediainfoList()); m_cur->directories.push_back(d); } m_cur = d; if (simple) { // To handle <Directory Name="..." /> endTag(name, Util::emptyString); } } } else if (name == sFileListing) { const string& b = getAttrib(attribs, sBase, 2); if (b.size() >= 1 && b[0] == '/' && b[b.size() - 1] == '/') { m_base = b; } if (m_base.size() > 1) // [+]PPA fix for [4](("Version", "1"),("CID", "EDI7OWB6TZWH6X6L2D3INC6ORQSG6RQDJ6AJ5QY"),("Base", "/"),("Generator", "DC++ 0.785")) { const StringTokenizer<string> sl(m_base.substr(1), '/'); for (auto i = sl.getTokens().cbegin(); i != sl.getTokens().cend(); ++i) { DirectoryListing::Directory* d = nullptr; for (auto j = m_cur->directories.cbegin(); j != m_cur->directories.cend(); ++j) { if ((*j)->getName() == *i) { d = *j; break; } } if (d == nullptr) { d = new DirectoryListing::Directory(m_list, m_cur, *i, false, false, isMediainfoList()); m_cur->directories.push_back(d); } m_cur = d; } } m_cur->setComplete(true); // [+] IRainman Delayed loading (dclst support) const string& l_cidStr = getAttrib(attribs, sCID, 2); if (l_cidStr.size() == 39) { const CID l_CID(l_cidStr); if (!l_CID.isZero()) { if (!m_user) { m_user = ClientManager::createUser(l_CID, "", 0); m_list->setHintedUser(HintedUser(m_user, Util::emptyString)); } } } const string& l_getIncludeSelf = getAttrib(attribs, sIncludeSelf, 2); m_list->setIncludeSelf(l_getIncludeSelf == "1"); // [~] IRainman Delayed loading (dclst support) m_is_in_listing = true; if (simple) { // To handle <Directory Name="..." /> endTag(name, Util::emptyString); } } }
void EmitCloseCaption( IRecipientFilter& filter, int entindex, bool fromplayer, char const *token, CUtlVector< Vector >& originlist, float duration, bool warnifmissing /*= false*/ ) { // No close captions in multiplayer... if ( gpGlobals->maxClients > 1 || (gpGlobals->maxClients==1 && !g_pClosecaption->GetBool())) { return; } // A negative duration means fill it in from the wav file if possible if ( duration < 0.0f ) { char const *wav = soundemitterbase->GetWavFileForSound( token, GENDER_NONE ); if ( wav ) { duration = enginesound->GetSoundDuration( wav ); } else { duration = 2.0f; } } char lowercase[ 256 ]; Q_strncpy( lowercase, token, sizeof( lowercase ) ); Q_strlower( lowercase ); if ( Q_strstr( lowercase, "\\" ) ) { Hack_FixEscapeChars( lowercase ); } // NOTE: We must make a copy or else if the filter is owned by a SoundPatch, we'll end up destructively removing // all players from it!!!! CRecipientFilter filterCopy; filterCopy.CopyFrom( (CRecipientFilter &)filter ); // Remove any players who don't want close captions CBaseEntity::RemoveRecipientsIfNotCloseCaptioning( (CRecipientFilter &)filterCopy ); #if !defined( CLIENT_DLL ) { // Defined in sceneentity.cpp bool AttenuateCaption( const char *token, const Vector& listener, CUtlVector< Vector >& soundorigins ); if ( filterCopy.GetRecipientCount() > 0 ) { int c = filterCopy.GetRecipientCount(); for ( int i = c - 1 ; i >= 0; --i ) { CBasePlayer *player = UTIL_PlayerByIndex( filterCopy.GetRecipientIndex( i ) ); if ( !player ) continue; Vector playerOrigin = player->GetAbsOrigin(); if ( AttenuateCaption( lowercase, playerOrigin, originlist ) ) { filterCopy.RemoveRecipient( player ); } } } } #endif // Anyone left? if ( filterCopy.GetRecipientCount() > 0 ) { #if !defined( CLIENT_DLL ) byte byteflags = 0; if ( warnifmissing ) { byteflags |= CLOSE_CAPTION_WARNIFMISSING; } if ( fromplayer ) { byteflags |= CLOSE_CAPTION_FROMPLAYER; } CBaseEntity *pActor = CBaseEntity::Instance( entindex ); if ( pActor ) { char const *pszActorModel = STRING( pActor->GetModelName() ); gender_t gender = soundemitterbase->GetActorGender( pszActorModel ); if ( gender == GENDER_MALE ) { byteflags |= CLOSE_CAPTION_GENDER_MALE; } else if ( gender == GENDER_FEMALE ) { byteflags |= CLOSE_CAPTION_GENDER_FEMALE; } } // Send caption and duration hint down to client UserMessageBegin( filterCopy, "CloseCaption" ); WRITE_STRING( lowercase ); WRITE_SHORT( MIN( 255, (int)( duration * 10.0f ) ) ), WRITE_BYTE( byteflags ), MessageEnd(); #else // Direct dispatch CHudCloseCaption *cchud = GET_HUDELEMENT( CHudCloseCaption ); if ( cchud ) { cchud->ProcessCaption( lowercase, duration, fromplayer ); } #endif } }
void EmitSoundByHandle( IRecipientFilter& filter, int entindex, const EmitSound_t & ep, HSOUNDSCRIPTHANDLE& handle ) { // Pull data from parameters CSoundParameters params; // Try to deduce the actor's gender gender_t gender = GENDER_NONE; CBaseEntity *ent = CBaseEntity::Instance( entindex ); if ( ent ) { char const *actorModel = STRING( ent->GetModelName() ); gender = soundemitterbase->GetActorGender( actorModel ); } if ( !soundemitterbase->GetParametersForSoundEx( ep.m_pSoundName, handle, params, gender, true ) ) { return; } if ( !params.soundname[0] ) return; #ifdef STAGING_ONLY if ( sv_snd_filter.GetString()[ 0 ] && !V_stristr( params.soundname, sv_snd_filter.GetString() )) { return; } if ( !Q_strncasecmp( params.soundname, "vo", 2 ) && !( params.channel == CHAN_STREAM || params.channel == CHAN_VOICE || params.channel == CHAN_VOICE2 ) ) { DevMsg( "EmitSound: Voice wave file %s doesn't specify CHAN_VOICE, CHAN_VOICE2 or CHAN_STREAM for sound %s\n", params.soundname, ep.m_pSoundName ); } #endif // STAGING_ONLY // handle SND_CHANGEPITCH/SND_CHANGEVOL and other sound flags.etc. if( ep.m_nFlags & SND_CHANGE_PITCH ) { params.pitch = ep.m_nPitch; } if( ep.m_nFlags & SND_CHANGE_VOL ) { params.volume = ep.m_flVolume; } #if !defined( CLIENT_DLL ) bool bSwallowed = CEnvMicrophone::OnSoundPlayed( entindex, params.soundname, params.soundlevel, params.volume, ep.m_nFlags, params.pitch, ep.m_pOrigin, ep.m_flSoundTime, ep.m_UtlVecSoundOrigin ); if ( bSwallowed ) return; #endif #if defined( _DEBUG ) && !defined( CLIENT_DLL ) if ( !enginesound->IsSoundPrecached( params.soundname ) ) { Msg( "Sound %s:%s was not precached\n", ep.m_pSoundName, params.soundname ); } #endif float st = ep.m_flSoundTime; if ( !st && params.delay_msec != 0 ) { st = gpGlobals->curtime + (float)params.delay_msec / 1000.f; } enginesound->EmitSound( filter, entindex, params.channel, params.soundname, params.volume, (soundlevel_t)params.soundlevel, ep.m_nFlags, params.pitch, ep.m_nSpecialDSP, ep.m_pOrigin, NULL, &ep.m_UtlVecSoundOrigin, true, st, ep.m_nSpeakerEntity ); if ( ep.m_pflSoundDuration ) { *ep.m_pflSoundDuration = enginesound->GetSoundDuration( params.soundname ); } TraceEmitSound( "EmitSound: '%s' emitted as '%s' (ent %i)\n", ep.m_pSoundName, params.soundname, entindex ); // Don't caption modulations to the sound if ( !( ep.m_nFlags & ( SND_CHANGE_PITCH | SND_CHANGE_VOL ) ) ) { EmitCloseCaption( filter, entindex, params, ep ); } #if defined( WIN32 ) && !defined( _X360 ) // NVNT notify the haptics system of this sound HapticProcessSound(ep.m_pSoundName, entindex); #endif }
/* Callback for JVMTI_EVENT_CLASS_FILE_LOAD_HOOK */ static void JNICALL cbClassFileLoadHook(jvmtiEnv *jvmti, JNIEnv* env, jclass class_being_redefined, jobject loader, const char* name, jobject protection_domain, jint class_data_len, const unsigned char* class_data, jint* new_class_data_len, unsigned char** new_class_data) { enter_critical_section(jvmti); { /* It's possible we get here right after VmDeath event, be careful */ if ( !gdata->vm_is_dead ) { const char *classname; /* Name could be NULL */ if ( name == NULL ) { classname = java_crw_demo_classname(class_data, class_data_len, NULL); if ( classname == NULL ) { fatal_error("ERROR: No classname inside classfile\n"); } } else { classname = strdup(name); if ( classname == NULL ) { fatal_error("ERROR: Out of malloc memory\n"); } } *new_class_data_len = 0; *new_class_data = NULL; /* The tracker class itself? */ if ( interested((char*)classname, "", gdata->include, gdata->exclude) && strcmp(classname, STRING(MTRACE_class)) != 0 ) { jint cnum; int system_class; unsigned char *new_image; long new_length; ClassInfo *cp; /* Get unique number for every class file image loaded */ cnum = gdata->ccount++; /* Save away class information */ if ( gdata->classes == NULL ) { gdata->classes = (ClassInfo*)malloc( gdata->ccount*sizeof(ClassInfo)); } else { gdata->classes = (ClassInfo*) realloc((void*)gdata->classes, gdata->ccount*sizeof(ClassInfo)); } if ( gdata->classes == NULL ) { fatal_error("ERROR: Out of malloc memory\n"); } cp = gdata->classes + cnum; cp->name = (const char *)strdup(classname); if ( cp->name == NULL ) { fatal_error("ERROR: Out of malloc memory\n"); } cp->calls = 0; cp->mcount = 0; cp->methods = NULL; /* Is it a system class? If the class load is before VmStart * then we will consider it a system class that should * be treated carefully. (See java_crw_demo) */ system_class = 0; if ( !gdata->vm_is_started ) { system_class = 1; } new_image = NULL; new_length = 0; /* Call the class file reader/write demo code */ java_crw_demo(cnum, classname, class_data, class_data_len, system_class, STRING(MTRACE_class), "L" STRING(MTRACE_class) ";", STRING(MTRACE_entry), "(II)V", STRING(MTRACE_exit), "(II)V", NULL, NULL, NULL, NULL, &new_image, &new_length, NULL, &mnum_callbacks); /* If we got back a new class image, return it back as "the" * new class image. This must be JVMTI Allocate space. */ if ( new_length > 0 ) { unsigned char *jvmti_space; jvmti_space = (unsigned char *)allocate(jvmti, (jint)new_length); (void)memcpy((void*)jvmti_space, (void*)new_image, (int)new_length); *new_class_data_len = (jint)new_length; *new_class_data = jvmti_space; /* VM will deallocate */ } /* Always free up the space we get from java_crw_demo() */ if ( new_image != NULL ) { (void)free((void*)new_image); /* Free malloc() space with free() */ } } (void)free((void*)classname); } } exit_critical_section(jvmti); }
//========================================================= // Precache - precaches all resources this NPC needs //========================================================= void CGenericActor::Precache() { PrecacheModel( STRING( GetModelName() ) ); }
//----------------------------------------------------------------------------- // Purpose: Returns whether or not it is OK to make an NPC at this instant. //----------------------------------------------------------------------------- bool CBaseNPCMaker::CanMakeNPC( bool bIgnoreSolidEntities ) { if( ai_inhibit_spawners.GetBool() ) return false; if ( m_nMaxLiveChildren > 0 && m_nLiveChildren >= m_nMaxLiveChildren ) {// not allowed to make a new one yet. Too many live ones out right now. return false; } if ( m_iszIngoreEnt != NULL_STRING ) { m_hIgnoreEntity = gEntList.FindEntityByName( NULL, m_iszIngoreEnt ); } Vector mins = GetAbsOrigin() - Vector( 34, 34, 0 ); Vector maxs = GetAbsOrigin() + Vector( 34, 34, 0 ); maxs.z = GetAbsOrigin().z; // If we care about not hitting solid entities, look for 'em if ( !bIgnoreSolidEntities ) { CBaseEntity *pList[128]; int count = UTIL_EntitiesInBox( pList, 128, mins, maxs, FL_CLIENT|FL_NPC ); if ( count ) { //Iterate through the list and check the results for ( int i = 0; i < count; i++ ) { //Don't build on top of another entity if ( pList[i] == NULL ) continue; //If one of the entities is solid, then we may not be able to spawn now if ( ( pList[i]->GetSolidFlags() & FSOLID_NOT_SOLID ) == false ) { // Since the outer method doesn't work well around striders on account of their huge bounding box. // Find the ground under me and see if a human hull would fit there. trace_t tr; UTIL_TraceHull( GetAbsOrigin() + Vector( 0, 0, 2 ), GetAbsOrigin() - Vector( 0, 0, 8192 ), NAI_Hull::Mins(HULL_HUMAN), NAI_Hull::Maxs(HULL_HUMAN), MASK_NPCSOLID, m_hIgnoreEntity, COLLISION_GROUP_NONE, &tr ); if( !HumanHullFits( tr.endpos + Vector( 0, 0, 1 ) ) ) { return false; } } } } } // Do we need to check to see if the player's looking? if ( HasSpawnFlags( SF_NPCMAKER_HIDEFROMPLAYER ) ) { for ( int i = 1; i <= gpGlobals->maxClients; i++ ) { CBasePlayer *pPlayer = UTIL_PlayerByIndex(i); if ( pPlayer ) { // Only spawn if the player's looking away from me if( pPlayer->FInViewCone( GetAbsOrigin() ) && pPlayer->FVisible( GetAbsOrigin() ) ) { if ( !(pPlayer->GetFlags() & FL_NOTARGET) ) return false; DevMsg( 2, "Spawner %s spawning even though seen due to notarget\n", STRING( GetEntityName() ) ); } } } } return true; }
void CFlextalkActor::ProcessSceneEvents( void ) { if ( HasSceneEvents() ) { BaseClass::ProcessSceneEvents( ); return; } // only do this if they have more than eyelid movement if (GetNumFlexControllers() > 2) { const char *pszExpression = flex_expression.GetString(); if (pszExpression && pszExpression[0] == '+' && pszExpression[1] != '\0') { int i; int j = atoi( &pszExpression[1] ); for (i = 0; i < GetNumFlexControllers(); i++) { m_flextarget[m_flexnum] = 0; } for (i = 0; i < 35 && predef_flexcontroller_names[i]; i++) { m_flexnum = LookupFlex( predef_flexcontroller_names[i] ); m_flextarget[m_flexnum] = predef_flexcontroller_values[j][i]; // Msg( "%s %.3f\n", predef_flexcontroller_names[i], predef_flexcontroller_values[j][i] ); } } else if (pszExpression && pszExpression[0] != '\0' && strcmp(pszExpression, "+") != 0) { char szExpression[128]; char szTemp[32]; Q_strncpy( szExpression, pszExpression ,sizeof(szExpression)); char *pszExpression = szExpression; while (*pszExpression != '\0') { if (*pszExpression == '+') *pszExpression = ' '; pszExpression++; } pszExpression = szExpression; while (*pszExpression) { if (*pszExpression != ' ') { if (*pszExpression == '-') { for (LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++) { m_flextarget[i] = 0; } } else if (*pszExpression == '?') { for (LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++) { Msg( "\"%s\" ", GetFlexControllerName( i ) ); } Msg( "\n" ); flex_expression.SetValue( "" ); } else { if (sscanf( pszExpression, "%31s", szTemp ) == 1) { m_flexnum = LookupFlex( szTemp ); if (m_flexnum != -1 && m_flextarget[m_flexnum] != 1) { m_flextarget[m_flexnum] = 1.0; // SetFlexTarget( m_flexnum ); } pszExpression += strlen( szTemp ) - 1; } } } pszExpression++; } } else if (m_flextime < gpGlobals->curtime) { m_flextime = gpGlobals->curtime + random->RandomFloat( 0.3, 0.5 ) * (30.0 / GetNumFlexControllers()); m_flexnum = (LocalFlexController_t)random->RandomInt( 0, GetNumFlexControllers() - 1 ); if (m_flextarget[m_flexnum] == 1) { m_flextarget[m_flexnum] = 0; } else if (stricmp( GetFlexControllerType( m_flexnum ), "phoneme" ) != 0) { if (strstr( GetFlexControllerName( m_flexnum ), "upper_raiser" ) == NULL) { Msg( "%s:%s\n", GetFlexControllerType( m_flexnum ), GetFlexControllerName( m_flexnum ) ); SetFlexTarget( m_flexnum, random->RandomFloat( 0.5, 1.0 ) ); } } } // slide it up. for (LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++) { float weight = GetFlexWeight( i ); if (weight != m_flextarget[i]) { weight = weight + (m_flextarget[i] - weight) / random->RandomFloat( 2.0, 4.0 ); } weight = clamp( weight, 0.0f, 1.0f ); SetFlexWeight( i, weight ); } if (flex_talk.GetInt() == -1) { m_istalking = 1; char pszSentence[256]; Q_snprintf( pszSentence,sizeof(pszSentence), "%s%d", STRING(m_iszSentence), m_sentence++ ); int sentenceIndex = engine->SentenceIndexFromName( pszSentence ); if (sentenceIndex >= 0) { Msg( "%d : %s\n", sentenceIndex, pszSentence ); CPASAttenuationFilter filter( this ); CBaseEntity::EmitSentenceByIndex( filter, entindex(), CHAN_VOICE, sentenceIndex, 1, SNDLVL_TALKING, 0, PITCH_NORM ); } else { m_sentence = 0; } flex_talk.SetValue( "0" ); } else if (flex_talk.GetInt() == -2) { m_flNextEyeLookTime = gpGlobals->curtime + 1000.0; } else if (flex_talk.GetInt() == -3) { m_flNextEyeLookTime = gpGlobals->curtime; flex_talk.SetValue( "0" ); } else if (flex_talk.GetInt() == -4) { AddLookTarget( UTIL_PlayerByIndex( 1 ), 0.5, flex_looktime.GetFloat() ); flex_talk.SetValue( "0" ); } else if (flex_talk.GetInt() == -5) { PickLookTarget( true ); flex_talk.SetValue( "0" ); } } }
//----------------------------------------------------------------------------- // Purpose: Creates the NPC. //----------------------------------------------------------------------------- void CNPCMaker::MakeNPC( void ) { if (!CanMakeNPC()) return; CAI_BaseNPC *pent = (CAI_BaseNPC*)CreateEntityByName( STRING(m_iszNPCClassname) ); if ( !pent ) { Warning("NULL Ent in NPCMaker!\n" ); return; } // ------------------------------------------------ // Intialize spawned NPC's relationships // ------------------------------------------------ pent->SetRelationshipString( m_RelationshipString ); m_OnSpawnNPC.Set( pent, pent, this ); pent->SetAbsOrigin( GetAbsOrigin() ); // Strip pitch and roll from the spawner's angles. Pass only yaw to the spawned NPC. QAngle angles = GetAbsAngles(); angles.x = 0.0; angles.z = 0.0; pent->SetAbsAngles( angles ); pent->AddSpawnFlags( SF_NPC_FALL_TO_GROUND ); if ( m_spawnflags & SF_NPCMAKER_FADE ) { pent->AddSpawnFlags( SF_NPC_FADE_CORPSE ); } pent->m_spawnEquipment = m_spawnEquipment; pent->SetSquadName( m_SquadName ); pent->SetHintGroup( m_strHintGroup ); ChildPreSpawn( pent ); DispatchSpawn( pent ); pent->SetOwnerEntity( this ); DispatchActivate( pent ); if ( m_ChildTargetName != NULL_STRING ) { // if I have a netname (overloaded), give the child NPC that name as a targetname pent->SetName( m_ChildTargetName ); } ChildPostSpawn( pent ); m_nLiveChildren++;// count this NPC if (!(m_spawnflags & SF_NPCMAKER_INF_CHILD)) { m_nMaxNumNPCs--; if ( IsDepleted() ) { m_OnAllSpawned.FireOutput( this, this ); // Disable this forever. Don't kill it because it still gets death notices SetThink( NULL ); SetUse( NULL ); } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CBaseDoor::Spawn() { Precache(); #ifdef HL1_DLL SetSolid( SOLID_BSP ); #else if ( GetMoveParent() && GetRootMoveParent()->GetSolid() == SOLID_BSP ) { SetSolid( SOLID_BSP ); } else { SetSolid( SOLID_VPHYSICS ); } #endif // Convert movedir from angles to a vector QAngle angMoveDir = QAngle( m_vecMoveDir.x, m_vecMoveDir.y, m_vecMoveDir.z ); AngleVectors( angMoveDir, &m_vecMoveDir ); SetModel( STRING( GetModelName() ) ); m_vecPosition1 = GetLocalOrigin(); // Subtract 2 from size because the engine expands bboxes by 1 in all directions making the size too big Vector vecOBB = CollisionProp()->OBBSize(); vecOBB -= Vector( 2, 2, 2 ); m_vecPosition2 = m_vecPosition1 + (m_vecMoveDir * (DotProductAbs( m_vecMoveDir, vecOBB ) - m_flLip)); if ( !IsRotatingDoor() ) { if ( ( m_eSpawnPosition == FUNC_DOOR_SPAWN_OPEN ) || HasSpawnFlags( SF_DOOR_START_OPEN_OBSOLETE ) ) { // swap pos1 and pos2, put door at pos2 UTIL_SetOrigin( this, m_vecPosition2); m_toggle_state = TS_AT_TOP; } else { m_toggle_state = TS_AT_BOTTOM; } } if (HasSpawnFlags(SF_DOOR_LOCKED)) { m_bLocked = true; } SetMoveType( MOVETYPE_PUSH ); if (m_flSpeed == 0) { m_flSpeed = 100; } SetTouch( &CBaseDoor::DoorTouch ); if ( !FClassnameIs( this, "func_water" ) ) { if ( HasSpawnFlags(SF_DOOR_PASSABLE) ) { //normal door AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID ); AddSolidFlags( FSOLID_NOT_SOLID ); } if ( HasSpawnFlags( SF_DOOR_NONSOLID_TO_PLAYER ) ) { SetCollisionGroup( COLLISION_GROUP_PASSABLE_DOOR ); // HACKHACK: Set this hoping that any children of the door that get blocked by the player // will get fixed up by vphysics // NOTE: We could decouple this as a separate behavior, but managing player collisions is already complex enough. // NOTE: This is necessary to prevent the player from blocking the wrecked train car in ep2_outland_01 AddFlag( FL_UNBLOCKABLE_BY_PLAYER ); } if ( m_bIgnoreDebris ) { // both of these flags want to set the collision group and // there isn't a combo group Assert( !HasSpawnFlags( SF_DOOR_NONSOLID_TO_PLAYER ) ); if ( HasSpawnFlags( SF_DOOR_NONSOLID_TO_PLAYER ) ) { Warning("Door %s with conflicting collision settings, removing ignoredebris\n", GetDebugName() ); } else { SetCollisionGroup( COLLISION_GROUP_INTERACTIVE ); } } } if ( ( m_eSpawnPosition == FUNC_DOOR_SPAWN_OPEN ) && HasSpawnFlags( SF_DOOR_START_OPEN_OBSOLETE ) ) { Warning("Door %s using obsolete 'Start Open' spawnflag with 'Spawn Position' set to 'Open'. Reverting to old behavior.\n", GetDebugName() ); } CreateVPhysics(); }
CNPCSpawnDestination *CTemplateNPCMaker::FindSpawnDestination() { CNPCSpawnDestination *pDestinations[ MAX_DESTINATION_ENTS ]; CBaseEntity *pEnt = NULL; CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); //BP CO HACK int count = 0; if( !pPlayer ) { return NULL; } // Collect all the qualifiying destination ents pEnt = gEntList.FindEntityByName( NULL, m_iszDestinationGroup ); if( !pEnt ) { DevWarning("Template NPC Spawner (%s) doesn't have any spawn destinations!\n", GetDebugName() ); return NULL; } while( pEnt ) { CNPCSpawnDestination *pDestination; pDestination = dynamic_cast <CNPCSpawnDestination*>(pEnt); if( pDestination && pDestination->IsAvailable() ) { bool fValid = true; Vector vecTest = pDestination->GetAbsOrigin(); if( m_CriterionVisibility != TS_YN_DONT_CARE ) { // Right now View Cone check is omitted intentionally. Vector vecTopOfHull = NAI_Hull::Maxs( HULL_HUMAN ); vecTopOfHull.x = 0; vecTopOfHull.y = 0; bool fVisible = (pPlayer->FVisible( vecTest ) || pPlayer->FVisible( vecTest + vecTopOfHull ) ); if( m_CriterionVisibility == TS_YN_YES ) { if( !fVisible ) fValid = false; } else { if( fVisible ) { if ( !(pPlayer->GetFlags() & FL_NOTARGET) ) fValid = false; else DevMsg( 2, "Spawner %s spawning even though seen due to notarget\n", STRING( GetEntityName() ) ); } } } if( fValid ) { pDestinations[ count ] = pDestination; count++; } } pEnt = gEntList.FindEntityByName( pEnt, m_iszDestinationGroup ); } if( count < 1 ) return NULL; // Now find the nearest/farthest based on distance criterion if( m_CriterionDistance == TS_DIST_DONT_CARE ) { // Pretty lame way to pick randomly. Try a few times to find a random // location where a hull can fit. Don't try too many times due to performance // concerns. for( int i = 0 ; i < 5 ; i++ ) { CNPCSpawnDestination *pRandomDest = pDestinations[ rand() % count ]; if( HumanHullFits( pRandomDest->GetAbsOrigin() ) ) { return pRandomDest; } } return NULL; } else { if( m_CriterionDistance == TS_DIST_NEAREST ) { float flNearest = FLT_MAX; CNPCSpawnDestination *pNearest = NULL; for( int i = 0 ; i < count ; i++ ) { Vector vecTest = pDestinations[ i ]->GetAbsOrigin(); float flDist = ( vecTest - pPlayer->GetAbsOrigin() ).Length(); if ( m_iMinSpawnDistance != 0 && m_iMinSpawnDistance > flDist ) continue; if( flDist < flNearest && HumanHullFits( vecTest ) ) { flNearest = flDist; pNearest = pDestinations[ i ]; } } return pNearest; } else { float flFarthest = 0; CNPCSpawnDestination *pFarthest = NULL; for( int i = 0 ; i < count ; i++ ) { Vector vecTest = pDestinations[ i ]->GetAbsOrigin(); float flDist = ( vecTest - pPlayer->GetAbsOrigin() ).Length(); if ( m_iMinSpawnDistance != 0 && m_iMinSpawnDistance > flDist ) continue; if( flDist > flFarthest && HumanHullFits( vecTest ) ) { flFarthest = flDist; pFarthest = pDestinations[ i ]; } } return pFarthest; } } return NULL; }
void CMonsterMaker :: Precache( void ) { CBaseMonster::Precache(); UTIL_PrecacheOther( STRING( m_iszMonsterClassname ) ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTemplateNPCMaker::MakeNPC( void ) { // If we should be using the radius spawn method instead, do so if ( m_flRadius && HasSpawnFlags(SF_NPCMAKER_ALWAYSUSERADIUS) ) { MakeNPCInRadius(); return; } if (!CanMakeNPC( ( m_iszDestinationGroup != NULL_STRING ) )) return; CNPCSpawnDestination *pDestination = NULL; if ( m_iszDestinationGroup != NULL_STRING ) { pDestination = FindSpawnDestination(); if ( !pDestination ) { DevMsg( 2, "%s '%s' failed to find a valid spawnpoint in destination group: '%s'\n", GetClassname(), STRING(GetEntityName()), STRING(m_iszDestinationGroup) ); return; } } CAI_BaseNPC *pent = NULL; CBaseEntity *pEntity = NULL; MapEntity_ParseEntity( pEntity, STRING(m_iszTemplateData), NULL ); if ( pEntity != NULL ) { pent = (CAI_BaseNPC *)pEntity; } if ( !pent ) { Warning("NULL Ent in NPCMaker!\n" ); return; } if ( pDestination ) { pent->SetAbsOrigin( pDestination->GetAbsOrigin() ); // Strip pitch and roll from the spawner's angles. Pass only yaw to the spawned NPC. QAngle angles = pDestination->GetAbsAngles(); angles.x = 0.0; angles.z = 0.0; pent->SetAbsAngles( angles ); pDestination->OnSpawnedNPC( pent ); } else { pent->SetAbsOrigin( GetAbsOrigin() ); // Strip pitch and roll from the spawner's angles. Pass only yaw to the spawned NPC. QAngle angles = GetAbsAngles(); angles.x = 0.0; angles.z = 0.0; pent->SetAbsAngles( angles ); } m_OnSpawnNPC.Set( pEntity, pEntity, this ); if ( m_spawnflags & SF_NPCMAKER_FADE ) { pent->AddSpawnFlags( SF_NPC_FADE_CORPSE ); } pent->RemoveSpawnFlags( SF_NPC_TEMPLATE ); if ( ( m_spawnflags & SF_NPCMAKER_NO_DROP ) == false ) { pent->RemoveSpawnFlags( SF_NPC_FALL_TO_GROUND ); // don't fall, slam } ChildPreSpawn( pent ); DispatchSpawn( pent ); pent->SetOwnerEntity( this ); DispatchActivate( pent ); ChildPostSpawn( pent ); m_nLiveChildren++;// count this NPC if (!(m_spawnflags & SF_NPCMAKER_INF_CHILD)) { m_nMaxNumNPCs--; if ( IsDepleted() ) { m_OnAllSpawned.FireOutput( this, this ); // Disable this forever. Don't kill it because it still gets death notices SetThink( NULL ); SetUse( NULL ); } } }
//----------------------------------------------------------------------------- // Purpose: Parse a keyvalues section into the prop // // pInteractionSection is a bit of jiggery-pokery to get around the unfortunate // fact that the interaction KV sections ("physgun_interactions", "fire_interactions", etc) // are OUTSIDE the "prop_data" KV section in the model, but may be contained WITHIN the // specified Base's "prop_data" section (i.e. in propdata.txt) //----------------------------------------------------------------------------- int CPropData::ParsePropFromKV( CBaseEntity *pProp, KeyValues *pSection, KeyValues *pInteractionSection ) { IBreakableWithPropData *pBreakableInterface = dynamic_cast<IBreakableWithPropData*>(pProp); if ( !pBreakableInterface ) return PARSE_FAILED_BAD_DATA; if ( !pBreakableInterface ) return PARSE_FAILED_BAD_DATA; int iBaseResult = PARSE_SUCCEEDED; // Do we have a base? char const *pszBase = pSection->GetString( "base" ); if ( pszBase && pszBase[0] ) { iBaseResult = ParsePropFromBase( pProp, pszBase ); if ( (iBaseResult != PARSE_SUCCEEDED) && (iBaseResult != PARSE_SUCCEEDED_ALLOWED_STATIC) ) return iBaseResult; } // Allow overriding of Block LOS int iBlockLOS = pSection->GetFloat( "blockLOS", -1 ); if ( iBlockLOS != -1 ) { pBreakableInterface->SetPropDataBlocksLOS( iBlockLOS != 0 ); } // Set whether AI can walk on this prop int iIsWalkable = pSection->GetFloat( "AIWalkable", -1 ); if ( iIsWalkable != -1 ) { pBreakableInterface->SetPropDataIsAIWalkable( iIsWalkable != 0 ); } // Set custom damage table const char *pszTableName; if ( pBreakableInterface->GetPhysicsDamageTable() == NULL_STRING ) { pszTableName = pSection->GetString( "damage_table", NULL ); } else { pszTableName = pSection->GetString( "damage_table", STRING(pBreakableInterface->GetPhysicsDamageTable()) ); } if ( pszTableName && pszTableName[0] ) { pBreakableInterface->SetPhysicsDamageTable( AllocPooledString( pszTableName ) ); } else { pBreakableInterface->SetPhysicsDamageTable( NULL_STRING ); } // Get multiplayer physics mode if not set by map pBreakableInterface->SetPhysicsMode( pSection->GetInt( "physicsmode", pBreakableInterface->GetPhysicsMode() ) ); const char *multiplayer_break = pSection->GetString( "multiplayer_break", NULL ); if ( multiplayer_break ) { mp_break_t mode = MULTIPLAYER_BREAK_DEFAULT; if ( FStrEq( multiplayer_break, "server" ) ) { mode = MULTIPLAYER_BREAK_SERVERSIDE; } else if ( FStrEq( multiplayer_break, "client" ) ) { mode = MULTIPLAYER_BREAK_CLIENTSIDE; } else if ( FStrEq( multiplayer_break, "both" ) ) { mode = MULTIPLAYER_BREAK_BOTH; } pBreakableInterface->SetMultiplayerBreakMode( mode ); } // Get damage modifiers, but only if they're specified, because our base may have already overridden them. pBreakableInterface->SetDmgModBullet( pSection->GetFloat( "dmg.bullets", pBreakableInterface->GetDmgModBullet() ) ); pBreakableInterface->SetDmgModClub( pSection->GetFloat( "dmg.club", pBreakableInterface->GetDmgModClub() ) ); pBreakableInterface->SetDmgModExplosive( pSection->GetFloat( "dmg.explosive", pBreakableInterface->GetDmgModExplosive() ) ); // Get the health (unless this is an override prop) if ( !FClassnameIs( pProp, "prop_physics_override" ) && !FClassnameIs( pProp, "prop_dynamic_override" ) ) { pProp->SetHealth( pSection->GetInt( "health", pProp->GetHealth() ) ); // Explosive? pBreakableInterface->SetExplosiveDamage( pSection->GetFloat( "explosive_damage", pBreakableInterface->GetExplosiveDamage() ) ); pBreakableInterface->SetExplosiveRadius( pSection->GetFloat( "explosive_radius", pBreakableInterface->GetExplosiveRadius() ) ); #ifdef GAME_DLL // If we now have health, we're not allowed to ignore physics damage if ( pProp->GetHealth() ) { pProp->RemoveSpawnFlags( SF_PHYSPROP_DONT_TAKE_PHYSICS_DAMAGE ); } #endif } const char *pszBreakableModel; if ( pBreakableInterface->GetBreakableModel() == NULL_STRING ) { pszBreakableModel = pSection->GetString( "breakable_model", NULL ); } else { pszBreakableModel = pSection->GetString( "breakable_model", STRING(pBreakableInterface->GetBreakableModel()) ); } if ( pszBreakableModel && pszBreakableModel[0] ) { pBreakableInterface->SetBreakableModel( AllocPooledString( pszBreakableModel ) ); } else { pBreakableInterface->SetBreakableModel( NULL_STRING ); } pBreakableInterface->SetBreakableSkin( pSection->GetInt( "breakable_skin", pBreakableInterface->GetBreakableSkin() ) ); pBreakableInterface->SetBreakableCount( pSection->GetInt( "breakable_count", pBreakableInterface->GetBreakableCount() ) ); // Calculate the maximum size of the breakables this breakable will produce Vector vecSize = pProp->CollisionProp()->OBBSize(); // Throw away the smallest coord int iSmallest = SmallestAxis(vecSize); vecSize[iSmallest] = 1; float flVolume = vecSize.x * vecSize.y * vecSize.z; int iMaxSize = floor( flVolume / (32.0*32.0) ); pBreakableInterface->SetMaxBreakableSize( iMaxSize ); // Now parse our interactions for ( int i = 0; i < PROPINTER_NUM_INTERACTIONS; i++ ) { // If we hit this assert, we have too many interactions for our current storage solution to handle Assert( i < 32 ); propdata_interaction_s *pInteraction = &sPropdataInteractionSections[i]; KeyValues *pkvCurrentInter = pInteractionSection->FindKey( pInteraction->pszSectionName ); if ( pkvCurrentInter ) { char const *pszInterBase = pkvCurrentInter->GetString( pInteraction->pszKeyName ); if ( pszInterBase && pszInterBase[0] && !stricmp( pszInterBase, pInteraction->pszValue ) ) { pBreakableInterface->SetInteraction( (propdata_interactions_t)i ); } } } // If the base said we're allowed to be static, return that if ( iBaseResult == PARSE_SUCCEEDED_ALLOWED_STATIC ) return PARSE_SUCCEEDED_ALLOWED_STATIC; // Otherwise, see if our propdata says we are allowed to be static if ( pSection->GetInt( "allowstatic", 0 ) ) return PARSE_SUCCEEDED_ALLOWED_STATIC; return PARSE_SUCCEEDED; }
string SettingItem::ToString::operator()(bool b) const { return b ? STRING(ENABLED) : STRING(DISABLED); }
void PropBreakableCreateAll( int modelindex, IPhysicsObject *pPhysics, const breakablepropparams_t ¶ms, CBaseEntity *pEntity, int iPrecomputedBreakableCount, bool bIgnoreGibLimit, bool defaultLocation ) { // Check for prop breakable count reset. int nPropCount = props_break_max_pieces_perframe.GetInt(); if ( nPropCount != -1 ) { if ( nFrameNumber != gpGlobals->framecount ) { nPropBreakablesPerFrameCount = 0; nFrameNumber = gpGlobals->framecount; } // Check for max breakable count for the frame. if ( nPropBreakablesPerFrameCount >= nPropCount ) return; } int iMaxBreakCount = bIgnoreGibLimit ? -1 : props_break_max_pieces.GetInt(); if ( iMaxBreakCount != -1 ) { if ( iPrecomputedBreakableCount != -1 ) { iPrecomputedBreakableCount = MIN( iMaxBreakCount, iPrecomputedBreakableCount ); } else { iPrecomputedBreakableCount = iMaxBreakCount; } } #ifdef GAME_DLL // On server limit break model creation if ( !PropBreakableCapEdictsOnCreateAll(modelindex, pPhysics, params, pEntity, iPrecomputedBreakableCount ) ) { DevMsg( "Failed to create PropBreakable: would exceed MAX_EDICTS\n" ); return; } #endif vcollide_t *pCollide = modelinfo->GetVCollide( modelindex ); if ( !pCollide ) return; int nSkin = 0; CBaseEntity *pOwnerEntity = pEntity; CBaseAnimating *pOwnerAnim = NULL; if ( pPhysics ) { pOwnerEntity = static_cast<CBaseEntity *>(pPhysics->GetGameData()); } if ( pOwnerEntity ) { pOwnerAnim = pOwnerEntity->GetBaseAnimating(); if ( pOwnerAnim ) { nSkin = pOwnerAnim->m_nSkin; } } matrix3x4_t localToWorld; CStudioHdr studioHdr; const model_t *model = modelinfo->GetModel( modelindex ); if ( model ) { studioHdr.Init( modelinfo->GetStudiomodel( model ) ); } Vector parentOrigin = vec3_origin; int parentAttachment = Studio_FindAttachment( &studioHdr, "placementOrigin" ) + 1; if ( parentAttachment > 0 ) { GetAttachmentLocalSpace( &studioHdr, parentAttachment-1, localToWorld ); MatrixGetColumn( localToWorld, 3, parentOrigin ); } else { AngleMatrix( vec3_angle, localToWorld ); } CUtlVector<breakmodel_t> list; BreakModelList( list, modelindex, params.defBurstScale, params.defCollisionGroup ); CUtlVector< CBaseEntity* > spawnedGibs; if ( list.Count() ) { for ( int i = 0; i < list.Count(); i++ ) { int modelIndex = modelinfo->GetModelIndex( list[i].modelName ); if ( modelIndex <= 0 ) continue; // Skip multiplayer pieces that should be spawning on the other dll #ifdef GAME_DLL if ( gpGlobals->maxClients > 1 && breakable_multiplayer.GetBool() ) #else if ( gpGlobals->maxClients > 1 ) #endif { #ifdef GAME_DLL if ( list[i].mpBreakMode == MULTIPLAYER_BREAK_CLIENTSIDE ) continue; #else if ( list[i].mpBreakMode == MULTIPLAYER_BREAK_SERVERSIDE ) continue; #endif if ( !defaultLocation && list[i].mpBreakMode == MULTIPLAYER_BREAK_DEFAULT ) continue; } if ( ( nPropCount != -1 ) && ( nPropBreakablesPerFrameCount > nPropCount ) ) break; if ( ( iPrecomputedBreakableCount != -1 ) && ( i >= iPrecomputedBreakableCount ) ) break; matrix3x4_t matrix; AngleMatrix( params.angles, params.origin, matrix ); CStudioHdr studioHdr; const model_t *model = modelinfo->GetModel( modelIndex ); if ( model ) { studioHdr.Init( modelinfo->GetStudiomodel( model ) ); } // Increment the number of breakable props this frame. ++nPropBreakablesPerFrameCount; const float flModelScale = pOwnerAnim->GetModelScale(); Vector position = vec3_origin; QAngle angles = params.angles; if ( pOwnerAnim && list[i].placementName[0] ) { if ( list[i].placementIsBone ) { int boneIndex = pOwnerAnim->LookupBone( list[i].placementName ); if ( boneIndex >= 0 ) { pOwnerAnim->GetBonePosition( boneIndex, position, angles ); AngleMatrix( angles, position, matrix ); } } else { int attachmentIndex = Studio_FindAttachment( &studioHdr, list[i].placementName ) + 1; if ( attachmentIndex > 0 ) { pOwnerAnim->GetAttachment( attachmentIndex, matrix ); MatrixAngles( matrix, angles ); } } } else { int placementIndex = Studio_FindAttachment( &studioHdr, "placementOrigin" ) + 1; Vector placementOrigin = parentOrigin; if ( placementIndex > 0 ) { GetAttachmentLocalSpace( &studioHdr, placementIndex-1, localToWorld ); MatrixGetColumn( localToWorld, 3, placementOrigin ); placementOrigin -= parentOrigin; } VectorTransform( list[i].offset - placementOrigin * flModelScale, matrix, position ); } Vector objectVelocity = params.velocity; if (pPhysics) { pPhysics->GetVelocityAtPoint( position, &objectVelocity ); } int nActualSkin = nSkin; if ( nActualSkin > studioHdr.numskinfamilies() ) nActualSkin = 0; CBaseEntity *pBreakable = NULL; #ifdef GAME_DLL if ( GetGibManager() == NULL || GetGibManager()->AllowedToSpawnGib() ) #endif { pBreakable = BreakModelCreateSingle( pOwnerEntity, &list[i], position, angles, objectVelocity, params.angularVelocity, nActualSkin, params ); } if ( pBreakable ) { spawnedGibs.AddToTail( pBreakable ); #ifdef GAME_DLL if ( GetGibManager() ) { GetGibManager()->AddGibToLRU( pBreakable->GetBaseAnimating() ); } #endif if ( pOwnerEntity && pOwnerEntity->IsEffectActive( EF_NOSHADOW ) ) { pBreakable->AddEffects( EF_NOSHADOW ); } // If burst scale is set, this piece should 'burst' away from // the origin in addition to travelling in the wished velocity. if ( list[i].burstScale != 0.0 ) { Vector vecBurstDir = position - params.origin; // If $autocenter wasn't used, try the center of the piece if ( vecBurstDir == vec3_origin ) { vecBurstDir = pBreakable->WorldSpaceCenter() - params.origin; } VectorNormalize( vecBurstDir ); pBreakable->ApplyAbsVelocityImpulse( vecBurstDir * list[i].burstScale * flModelScale * params.velocityScale * params.burstScale ); } if ( params.randomAngularVelocity > 0.0f ) { AngularImpulse angRandomImpulse = RandomAngularImpulse( -params.randomAngularVelocity, params.randomAngularVelocity ); pBreakable->ApplyLocalAngularVelocityImpulse( angRandomImpulse * params.velocityScale ); } // If this piece is supposed to be motion disabled, disable it if ( list[i].isMotionDisabled ) { IPhysicsObject *pPhysicsObject = pBreakable->VPhysicsGetObject(); if ( pPhysicsObject != NULL ) { pPhysicsObject->EnableMotion( false ); } } } } } // Then see if the propdata specifies any breakable pieces else if ( pEntity ) { IBreakableWithPropData *pBreakableInterface = dynamic_cast<IBreakableWithPropData*>(pEntity); if ( pBreakableInterface && pBreakableInterface->GetBreakableModel() != NULL_STRING && pBreakableInterface->GetBreakableCount() ) { breakmodel_t breakModel; for ( int i = 0; i < pBreakableInterface->GetBreakableCount(); i++ ) { if ( ( iPrecomputedBreakableCount != -1 ) && ( i >= iPrecomputedBreakableCount ) ) break; Q_strncpy( breakModel.modelName, g_PropDataSystem.GetRandomChunkModel(STRING(pBreakableInterface->GetBreakableModel()), pBreakableInterface->GetMaxBreakableSize()), sizeof(breakModel.modelName) ); breakModel.health = 1; breakModel.fadeTime = RandomFloat(5,10); breakModel.fadeMinDist = 0.0f; breakModel.fadeMaxDist = 0.0f; breakModel.burstScale = params.defBurstScale; breakModel.collisionGroup = COLLISION_GROUP_DEBRIS; breakModel.isRagdoll = false; breakModel.isMotionDisabled = false; breakModel.placementName[0] = 0; breakModel.placementIsBone = false; Vector vecObbSize = pEntity->CollisionProp()->OBBSize(); // Find a random point on the plane of the original's two largest axis int smallestAxis = SmallestAxis( vecObbSize ); Vector vecMins(0,0,0); Vector vecMaxs(1,1,1); vecMins[smallestAxis] = 0.5; vecMaxs[smallestAxis] = 0.5; pEntity->CollisionProp()->RandomPointInBounds( vecMins, vecMaxs, &breakModel.offset ); // Push all chunks away from the center Vector vecBurstDir = breakModel.offset - params.origin; VectorNormalize( vecBurstDir ); Vector vecVelocity = vecBurstDir * params.defBurstScale; QAngle vecAngles = pEntity->GetAbsAngles(); int iSkin = pBreakableInterface->GetBreakableSkin(); CBaseEntity *pBreakable = NULL; #ifdef GAME_DLL if ( GetGibManager() == NULL || GetGibManager()->AllowedToSpawnGib() ) #endif { pBreakable = BreakModelCreateSingle( pOwnerEntity, &breakModel, breakModel.offset, vecAngles, vecVelocity, vec3_origin/*params.angularVelocity*/, iSkin, params ); if ( !pBreakable ) { DevWarning( "PropBreakableCreateAll: Could not create model %s\n", breakModel.modelName ); } } if ( pBreakable ) { #ifdef GAME_DLL if ( GetGibManager() ) { GetGibManager()->AddGibToLRU( pBreakable->GetBaseAnimating() ); } #endif Vector vecBreakableObbSize = pBreakable->CollisionProp()->OBBSize(); // Try to align the gibs along the original axis matrix3x4_t matrix; AngleMatrix( vecAngles, matrix ); AlignBoxes( &matrix, vecObbSize, vecBreakableObbSize ); MatrixAngles( matrix, vecAngles ); if ( pBreakable->VPhysicsGetObject() ) { Vector pos; pBreakable->VPhysicsGetObject()->GetPosition( &pos, NULL ); pBreakable->VPhysicsGetObject()->SetPosition( pos, vecAngles, true ); } pBreakable->SetAbsAngles( vecAngles ); if ( pOwnerEntity->IsEffectActive( EF_NOSHADOW ) ) { pBreakable->AddEffects( EF_NOSHADOW ); } } } } } if ( params.connectingParticleNames.Count() > 0 && spawnedGibs.Count() > 1 ) { const int iGibCount = spawnedGibs.Count(); int iParticlesLeft = iGibCount / 2; int iEntIndex0 = RandomInt( 0, iGibCount - 1 ); while ( iParticlesLeft > 0 ) { iParticlesLeft--; const int iEntIndex1 = ( iEntIndex0 + RandomInt( 1, iGibCount - 1 ) ) % iGibCount; CBaseEntity *pEnt0 = spawnedGibs[ iEntIndex0 ]; CBaseEntity *pEnt1 = spawnedGibs[ iEntIndex1 ]; const int iParticleSystemIndex = RandomInt( 0, params.connectingParticleNames.Count() - 1 ); DispatchParticleEffect( params.connectingParticleNames[ iParticleSystemIndex ], pEnt0, pEnt1 ); iEntIndex0 = ( iEntIndex0 + RandomInt( 1, iGibCount - 1 ) ) % iGibCount; } } }
void CBreakable::Precache( void ) { const char *pGibName = "WoodChunks"; switch (m_Material) { case matWood: pGibName = "WoodChunks"; break; case matUnbreakableGlass: case matGlass: pGibName = "GlassChunks"; break; case matMetal: pGibName = "MetalChunks"; break; case matRocks: pGibName = "ConcreteChunks"; break; #ifdef HL1_DLL case matComputer: pGibName = "ComputerGibs"; break; case matCeilingTile: pGibName = "CeilingTile"; break; case matFlesh: pGibName = "FleshGibs"; break; case matCinderBlock: pGibName = "CinderBlocks"; break; case matWeb: pGibName = "WebGibs"; break; #else case matCinderBlock: pGibName = "ConcreteChunks"; break; #endif #if HL2_EPISODIC case matNone: pGibName = ""; break; #endif default: Warning("%s (%s) at (%.3f %.3f %.3f) using obsolete or unknown material type.\n", GetClassname(), GetDebugName(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z ); pGibName = "WoodChunks"; break; } if ( m_iszGibModel != NULL_STRING ) { pGibName = STRING(m_iszGibModel); #ifdef HL1_DLL PrecacheModel( pGibName ); #endif } m_iszModelName = MAKE_STRING( pGibName ); // Precache the spawn item's data if ( !CommandLine()->CheckParm("-makereslists")) { if ( m_iszSpawnObject != NULL_STRING ) { UTIL_PrecacheOther( STRING( m_iszSpawnObject ) ); } } else { // Actually, precache all possible objects... for ( int i = 0; i < ARRAYSIZE(pSpawnObjects) ; ++i ) { if ( !pSpawnObjects[ i ] ) continue; if ( !Q_strnicmp( pSpawnObjects[ i ], "unused", Q_strlen( "unused" ) ) ) continue; UTIL_PrecacheOther( pSpawnObjects[ i ] ); } } PrecacheScriptSound( "Breakable.MatGlass" ); PrecacheScriptSound( "Breakable.MatWood" ); PrecacheScriptSound( "Breakable.MatMetal" ); PrecacheScriptSound( "Breakable.MatFlesh" ); PrecacheScriptSound( "Breakable.MatConcrete" ); PrecacheScriptSound( "Breakable.Computer" ); PrecacheScriptSound( "Breakable.Crate" ); PrecacheScriptSound( "Breakable.Glass" ); PrecacheScriptSound( "Breakable.Metal" ); PrecacheScriptSound( "Breakable.Flesh" ); PrecacheScriptSound( "Breakable.Concrete" ); PrecacheScriptSound( "Breakable.Ceiling" ); }
/* lex a source buffer for a program */ L_TOKEN* LexSourceBuffer(const char* source_buffer, char** stripped, GRAMMAR_TABLE table) { const char* buffer; char* format; int* lineNumbers; int line; int size; int i, j; int a, b; L_TOKEN* start = NULL; L_TOKEN* end = NULL; buffer = source_buffer; size = strlen(buffer); // count lines lineNumbers = (int*)malloc((size+1)*sizeof(int)); line = 0; for (i = 0; i <= size; i++) { lineNumbers[i] = line; if (buffer[i] == '\n') line++; } // strip clean format = (char*)malloc(size+1); j = 0; for (i = 0; i < size; i++) { if (buffer[i] == '/' && buffer[i+1] == '/') { // inline comments while (i < size && buffer[i] != '\n') i++; i--; } else if (buffer[i] == '/' && buffer[i+1] == '*') { // multiline comments i++; i++; while (i < size - 1 && (buffer[i] != '*' || buffer[i+1] != '/')) { i++; } i++; } #ifdef IGNORE_MACROS else if (buffer[i] == '#') { while (i < size && buffer[i] != '\n') i++; i--; } #endif #ifdef SEMICOLON_COMMENTS else if (buffer[i] == ';') { while (i < size && buffer[i] != '\n') i++; i--; } #endif else if (isSpace(buffer[i])) { // whitespace format[j] = ' '; lineNumbers[j] = lineNumbers[i]; while (i < size && isSpace(buffer[i])) { if (buffer[i] == '\n') { format[j] = '\n'; lineNumbers[j] = lineNumbers[i]; } i++; } i--; j++; } else if (buffer[i] == '"' || buffer[i] == '\'') { char quote = buffer[i]; // string format[j++] = buffer[i++]; while (i < size - 1 && buffer[i] != quote) { if (buffer[i] == '\\') { lineNumbers[j] = lineNumbers[i]; format[j++] = buffer[i++]; } lineNumbers[j] = lineNumbers[i]; format[j++] = buffer[i++]; } lineNumbers[j] = lineNumbers[i]; format[j++] = buffer[i]; } else { // character lineNumbers[j] = lineNumbers[i]; format[j] = buffer[i]; j++; } } format[j] = 0; size = j; // lex // printf("Lexing...\n\n"); for (i = 0; i < size; i++) { line = lineNumbers[i]; if (isAlpha(format[i])) { a = i; // alpha while (i < size && (isAlpha(format[i]) || isNumeric(format[i]) || format[i] == '_')) { i++; } b = i; LexAddBlock(&start, &end, IDENTIFIER(format, a, b, line, table)); i--; } else if (isNumeric(format[i])) { // numeric a = i; while (i < size && isNumeric(format[i])) { i++; } if (format[i] == '.') { i++; while (i < size && isNumeric(format[i])) { i++; } b = i; LexAddBlock(&start, &end, FLOAT(format, a, b, line)); i--; } else { b = i; LexAddBlock(&start, &end, INTEGER(format, a, b, line)); i--; } } else if (format[i] == '"' || format[i] == '\'') { char delimiter = format[i]; // string a = i++; while (i < size && format[i] != delimiter) { i++; } b = i++; LexAddBlock(&start, &end, STRING(format, a, b+1, line)); i--; } else if (isGlyph(format[i])) { a = i; b = 0; // symbol while (i < size && isGlyph(format[i])) { i++; if (FindToken(&format[a], i - a, table)) b = i; } b = b ? b : i; LexAddBlock(&start, &end, TOKEN(format, a, b, line, table)); i = b - 1; } else if (format[i] == '\n') { #ifdef LEX_NEWLINES // end line LexAddBlock(&start, &end, NEWLINE(line)); #endif } else if (format[i] == ' ') { // whitespace } else { // ? PrintLexing(start); printf("Syntax error on line %i: ", line+1); printf("Illegal token %i.\n", format[i]); FreeLexing(start, format); *stripped = 0; return NULL; } } #ifdef LEX_NEWLINES // add newline to the end LexAddBlock(&start, &end, NEWLINE(line)); #endif // add $ to the end LexAddBlock(&start, &end, EOFSYMBOL(line)); free(lineNumbers); *stripped = format; return start; }
//----------------------------------------------------------------------------- // Purpose: Breaks the breakable. m_hBreaker is the entity that caused us to break. //----------------------------------------------------------------------------- void CBreakable::Die( void ) { Vector vecVelocity;// shard velocity char cFlag = 0; int pitch; float fvol; pitch = 95 + random->RandomInt(0,29); if (pitch > 97 && pitch < 103) { pitch = 100; } // The more negative m_iHealth, the louder // the sound should be. fvol = random->RandomFloat(0.85, 1.0) + (abs(m_iHealth) / 100.0); if (fvol > 1.0) { fvol = 1.0; } const char *soundname = NULL; switch (m_Material) { default: break; case matGlass: soundname = "Breakable.Glass"; cFlag = BREAK_GLASS; break; case matWood: soundname = "Breakable.Crate"; cFlag = BREAK_WOOD; break; case matComputer: soundname = "Breakable.Computer"; cFlag = BREAK_METAL; break; case matMetal: soundname = "Breakable.Metal"; cFlag = BREAK_METAL; break; case matFlesh: case matWeb: soundname = "Breakable.Flesh"; cFlag = BREAK_FLESH; break; case matRocks: case matCinderBlock: soundname = "Breakable.Concrete"; cFlag = BREAK_CONCRETE; break; case matCeilingTile: soundname = "Breakable.Ceiling"; break; } if ( soundname ) { if ( m_hBreaker && m_hBreaker->IsPlayer() ) { IGameEvent * event = gameeventmanager->CreateEvent( "break_breakable" ); if ( event ) { event->SetInt( "userid", ToBasePlayer( m_hBreaker )->GetUserID() ); event->SetInt( "entindex", entindex() ); event->SetInt( "material", cFlag ); gameeventmanager->FireEvent( event ); } } CSoundParameters params; if ( GetParametersForSound( soundname, params, NULL ) ) { CPASAttenuationFilter filter( this ); EmitSound_t ep; ep.m_nChannel = params.channel; ep.m_pSoundName = params.soundname; ep.m_flVolume = fvol; ep.m_SoundLevel = params.soundlevel; ep.m_nPitch = pitch; EmitSound( filter, entindex(), ep ); } } switch( m_Explosion ) { case expDirected: vecVelocity = g_vecAttackDir * -200; break; case expUsePrecise: { AngleVectors( m_GibDir, &vecVelocity, NULL, NULL ); vecVelocity *= 200; } break; case expRandom: vecVelocity.x = 0; vecVelocity.y = 0; vecVelocity.z = 0; break; default: DevMsg("**ERROR - Unspecified gib dir method in func_breakable!\n"); break; } Vector vecSpot = WorldSpaceCenter(); CPVSFilter filter2( vecSpot ); int iModelIndex = 0; CCollisionProperty *pCollisionProp = CollisionProp(); Vector vSize = pCollisionProp->OBBSize(); int iCount = ( vSize[0] * vSize[1] + vSize[1] * vSize[2] + vSize[2] * vSize[0] ) / ( 3 * 12 * 12 ); if ( iCount > func_break_max_pieces.GetInt() ) { iCount = func_break_max_pieces.GetInt(); } ConVarRef breakable_disable_gib_limit( "breakable_disable_gib_limit" ); if ( !breakable_disable_gib_limit.GetBool() && iCount ) { if ( m_PerformanceMode == PM_NO_GIBS ) { iCount = 0; } else if ( m_PerformanceMode == PM_REDUCED_GIBS ) { int iNewCount = iCount * func_break_reduction_factor.GetFloat(); iCount = max( iNewCount, 1 ); } } if ( m_iszModelName != NULL_STRING ) { for ( int i = 0; i < iCount; i++ ) { #ifdef HL1_DLL // Use the passed model instead of the propdata type const char *modelName = STRING( m_iszModelName ); // if the map specifies a model by name if( strstr( modelName, ".mdl" ) != NULL ) { iModelIndex = modelinfo->GetModelIndex( modelName ); } else // do the hl2 / normal way #endif iModelIndex = modelinfo->GetModelIndex( g_PropDataSystem.GetRandomChunkModel( STRING( m_iszModelName ) ) ); // All objects except the first one in this run are marked as slaves... int slaveFlag = 0; if ( i != 0 ) { slaveFlag = BREAK_SLAVE; } te->BreakModel( filter2, 0.0, vecSpot, pCollisionProp->GetCollisionAngles(), vSize, vecVelocity, iModelIndex, 100, 1, 2.5, cFlag | slaveFlag ); } } ResetOnGroundFlags(); // Don't fire something that could fire myself SetName( NULL_STRING ); AddSolidFlags( FSOLID_NOT_SOLID ); // Fire targets on break m_OnBreak.FireOutput( m_hBreaker, this ); VPhysicsDestroyObject(); SetThink( &CBreakable::SUB_Remove ); SetNextThink( gpGlobals->curtime + 0.1f ); if ( m_iszSpawnObject != NULL_STRING ) { CBaseEntity::Create( STRING(m_iszSpawnObject), vecSpot, pCollisionProp->GetCollisionAngles(), this ); } if ( Explodable() ) { ExplosionCreate( vecSpot, pCollisionProp->GetCollisionAngles(), this, GetExplosiveDamage(), GetExplosiveRadius(), true ); } }
void CWorld::Precache( void ) { g_WorldEntity = this; g_fGameOver = false; //BG2 - Tjoppen - away with these //g_pLastSpawn = NULL; // ConVarRef stepsize( "sv_stepsize" ); stepsize.SetValue( 18 ); ConVarRef roomtype( "room_type" ); roomtype.SetValue( 0 ); // Set up game rules Assert( !g_pGameRules ); if (g_pGameRules) { delete g_pGameRules; } InstallGameRules(); Assert( g_pGameRules ); g_pGameRules->Init(); CSoundEnt::InitSoundEnt(); // Only allow precaching between LevelInitPreEntity and PostEntity CBaseEntity::SetAllowPrecache( true ); IGameSystem::LevelInitPreEntityAllSystems( STRING( GetModelName() ) ); // Create the player resource g_pGameRules->CreateStandardEntities(); // UNDONE: Make most of these things server systems or precache_registers // ================================================= // Activities // ================================================= ActivityList_Free(); RegisterSharedActivities(); EventList_Free(); RegisterSharedEvents(); InitBodyQue(); // init sentence group playback stuff from sentences.txt. // ok to call this multiple times, calls after first are ignored. SENTENCEG_Init(); // Precache standard particle systems PrecacheStandardParticleSystems( ); // the area based ambient sounds MUST be the first precache_sounds // player precaches W_Precache (); // get weapon precaches ClientPrecache(); g_pGameRules->Precache(); // precache all temp ent stuff CBaseTempEntity::PrecacheTempEnts(); g_Language.SetValue( LANGUAGE_ENGLISH ); // TODO use VGUI to get current language if ( g_Language.GetInt() == LANGUAGE_GERMAN ) { PrecacheModel( "models/germangibs.mdl" ); } else { PrecacheModel( "models/gibs/hgibs.mdl" ); } PrecacheScriptSound( "BaseEntity.EnterWater" ); PrecacheScriptSound( "BaseEntity.ExitWater" ); // // Setup light animation tables. 'a' is total darkness, 'z' is maxbright. // for ( int i = 0; i < ARRAYSIZE(g_DefaultLightstyles); i++ ) { engine->LightStyle( i, GetDefaultLightstyleString(i) ); } // styles 32-62 are assigned by the light program for switchable lights // 63 testing engine->LightStyle(63, "a"); // ================================================= // Load and Init AI Networks // ================================================= CAI_NetworkManager::InitializeAINetworks(); // ================================================= // Load and Init AI Schedules // ================================================= g_AI_SchedulesManager.LoadAllSchedules(); // ================================================= // Initialize NPC Relationships // ================================================= g_pGameRules->InitDefaultAIRelationships(); CBaseCombatCharacter::InitInteractionSystem(); // Call all registered precachers. CPrecacheRegister::Precache(); if ( m_iszChapterTitle != NULL_STRING ) { DevMsg( 2, "Chapter title: %s\n", STRING(m_iszChapterTitle) ); CMessage *pMessage = (CMessage *)CBaseEntity::Create( "env_message", vec3_origin, vec3_angle, NULL ); if ( pMessage ) { pMessage->SetMessage( m_iszChapterTitle ); m_iszChapterTitle = NULL_STRING; // send the message entity a play message command, delayed by 1 second pMessage->AddSpawnFlags( SF_MESSAGE_ONCE ); pMessage->SetThink( &CMessage::SUB_CallUseToggle ); pMessage->SetNextThink( gpGlobals->curtime + 1.0f ); } } g_iszFuncBrushClassname = AllocPooledString("func_brush"); }
int CFriend :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType) { // make sure friends talk about it if player hurts talkmonsters... int ret = CTalkMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); if ( !IsAlive() || pev->deadflag == DEAD_DYING ) return ret; // LRC - if my reaction to the player has been overridden, don't do this stuff if (m_iPlayerReact) return ret; if ( m_MonsterState != MONSTERSTATE_PRONE && (pevAttacker->flags & FL_CLIENT) ) { // This is a heurstic to determine if the player intended to harm me // If I have an enemy, we can't establish intent (may just be crossfire) if ( m_hEnemy == NULL ) { // If the player was facing directly at me, or I'm already suspicious, get mad if ( (m_afMemory & bits_MEMORY_SUSPICIOUS) || IsFacing( pevAttacker, pev->origin ) ) { // Alright, now I'm pissed! if (m_iszSpeakAs) { char szBuf[32]; strcpy(szBuf,STRING(m_iszSpeakAs)); strcat(szBuf,"_MAD"); PlaySentence( szBuf, 4, VOL_NORM, ATTN_NORM ); } else { PlaySentence( "FG_MAD", 4, VOL_NORM, ATTN_NORM ); } Remember( bits_MEMORY_PROVOKED ); StopFollowing( TRUE ); } else { // Hey, be careful with that if (m_iszSpeakAs) { char szBuf[32]; strcpy(szBuf,STRING(m_iszSpeakAs)); strcat(szBuf,"_SHOT"); PlaySentence( szBuf, 4, VOL_NORM, ATTN_NORM ); } else { PlaySentence( "FG_SHOT", 4, VOL_NORM, ATTN_NORM ); } Remember( bits_MEMORY_SUSPICIOUS ); } } else if ( !(m_hEnemy->IsPlayer()) && pev->deadflag == DEAD_NO ) { if (m_iszSpeakAs) { char szBuf[32]; strcpy(szBuf,STRING(m_iszSpeakAs)); strcat(szBuf,"_SHOT"); PlaySentence( szBuf, 4, VOL_NORM, ATTN_NORM ); } else { PlaySentence( "FG_SHOT", 4, VOL_NORM, ATTN_NORM ); } } } return ret; }