static int CC_asw_teleport_autocomplete( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] ) { if ( !g_pGameRules ) { return 0; } char const *cmdname = "asw_teleport"; char *substring = (char *)partial; if ( Q_strstr( partial, cmdname ) ) { substring = (char *)partial + strlen( cmdname ) + 1; } int checklen = Q_strlen( substring ); CUtlSymbolTable entries( 0, 0, true ); CUtlVector< CUtlSymbol > symbols; CBaseEntity *pos = NULL; while ( ( pos = gEntList.NextEnt( pos ) ) != NULL ) { // Check target name against partial string if ( pos->GetEntityName() == NULL_STRING ) continue; if ( Q_strnicmp( STRING( pos->GetEntityName() ), substring, checklen ) ) continue; CUtlSymbol sym = entries.AddString( STRING( pos->GetEntityName() ) ); int idx = symbols.Find( sym ); if ( idx == symbols.InvalidIndex() ) { symbols.AddToTail( sym ); } // Too many if ( symbols.Count() >= COMMAND_COMPLETION_MAXITEMS ) break; } // Now fill in the results for ( int i = 0; i < symbols.Count(); i++ ) { char const *name = entries.String( symbols[ i ] ); char buf[ 512 ]; Q_strncpy( buf, name, sizeof( buf ) ); Q_strlower( buf ); Q_snprintf( commands[ i ], COMMAND_COMPLETION_ITEM_LENGTH, "%s %s", cmdname, buf ); } return symbols.Count(); }
//----------------------------------------------------------------------------- // Purpose: Input handler that converts our target to a physics object. //----------------------------------------------------------------------------- void CPhysConvert::InputConvertTarget( inputdata_t &inputdata ) { bool createAsleep = HasSpawnFlags(SF_CONVERT_ASLEEP); // Fire output m_OnConvert.FireOutput( inputdata.pActivator, this ); CBaseEntity *entlist[512]; CBaseEntity *pSwap = gEntList.FindEntityByName( NULL, m_swapModel, inputdata.pActivator ); CBaseEntity *pEntity = NULL; int count = 0; while ( (pEntity = gEntList.FindEntityByName( pEntity, m_target, inputdata.pActivator )) != NULL ) { entlist[count++] = pEntity; if ( count >= ARRAYSIZE(entlist) ) break; } // if we're swapping to model out, don't loop over more than one object // multiple objects with the same brush model will render, but the dynamic lights // and decals will be shared between the two instances... if ( pSwap && count > 0 ) { count = 1; } for ( int i = 0; i < count; i++ ) { pEntity = entlist[i]; // don't convert something that is already physics based if ( pEntity->GetMoveType() == MOVETYPE_VPHYSICS ) { Msg( "ERROR phys_convert %s ! Already MOVETYPE_VPHYSICS\n", STRING(pEntity->m_iClassname) ); continue; } UnlinkFromParent( pEntity ); if ( pSwap ) { // we can't reuse this physics object, so kill it pEntity->VPhysicsDestroyObject(); pEntity->SetModel( STRING(pSwap->GetModelName()) ); } CBaseEntity *pPhys = CreateSimplePhysicsObject( pEntity, createAsleep ); // created phys object, now move hierarchy over if ( pPhys ) { pPhys->SetName( pEntity->GetEntityName() ); TransferChildren( pEntity, pPhys ); pEntity->AddSolidFlags( FSOLID_NOT_SOLID ); pEntity->m_fEffects |= EF_NODRAW; UTIL_Relink( pEntity ); UTIL_Remove( pEntity ); } } }
void CTFOClassnameFinder::FindTarget( inputdata_t &inputdata ) { bool bFound = false; CBaseEntity *pMyFoundEnt = NULL; // Try classname pMyFoundEnt = gEntList.FindEntityByClassname( NULL, szTarget.ToCStr() ); while ( pMyFoundEnt ) { if ( !strcmp( pMyFoundEnt->GetClassname(), szTarget.ToCStr() ) ) { pFoundTarget.FireOutput( this, this ); bFound = true; break; } pMyFoundEnt = gEntList.FindEntityByClassname( pMyFoundEnt, szTarget.ToCStr() ); } if ( bFound ) return; // Try the actual name pMyFoundEnt = gEntList.FindEntityByName( NULL, szTarget.ToCStr() ); while ( pMyFoundEnt ) { if ( !strcmp( pMyFoundEnt->GetEntityName().ToCStr(), szTarget.ToCStr() ) ) { pFoundTarget.FireOutput( this, this ); break; } pMyFoundEnt = gEntList.FindEntityByName( pMyFoundEnt, szTarget.ToCStr() ); } }
// Find a player with a case-insensitive name search. static CBasePlayer* FindPlayerByName(const char *pTestName) { for(int i=1; i <= gpGlobals->maxClients; i++) { edict_t *pEdict = engine->PEntityOfEntIndex(i); if(pEdict) { CBaseEntity *pEnt = CBaseEntity::Instance(pEdict); if(pEnt && pEnt->IsPlayer()) { const char *pNetName = STRING(pEnt->GetEntityName()); if(stricmp(pNetName, pTestName) == 0) { return (CBasePlayer*)pEnt; } } } } return NULL; }
entityIndex = trace.m_pEnt ? (short)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 ) {
//----------------------------------------------------------------------------- // Purpose: We've hit a waypoint. Handle it, and return true if this is the // end of the path. //----------------------------------------------------------------------------- bool CNPC_VehicleDriver::WaypointReached( void ) { // We reached our current waypoint. m_vecPrevPrevPoint = m_vecPrevPoint; m_vecPrevPoint = GetAbsOrigin(); // If we've got to our goal, we're done here. if ( GetNavigator()->CurWaypointIsGoal() ) { // Necessary for InPass outputs to be fired, is a no-op otherwise GetNavigator()->AdvancePath(); // Stop pathing ClearWaypoints(); TaskComplete(); SetGoalEnt( NULL ); return true; } AI_Waypoint_t *pCurWaypoint = GetNavigator()->GetPath()->GetCurWaypoint(); if ( !pCurWaypoint ) return false; // Check to see if the waypoint wants us to change speed if ( pCurWaypoint->Flags() & bits_WP_TO_PATHCORNER ) { CBaseEntity *pEntity = pCurWaypoint->hPathCorner; if ( pEntity ) { if ( pEntity->m_flSpeed > 0 ) { if ( pEntity->m_flSpeed <= 1.0 ) { m_flDriversMaxSpeed = pEntity->m_flSpeed; RecalculateSpeeds(); } else { Warning("path_track %s tried to tell the npc_vehicledriver to set speed to %.3f. npc_vehicledriver only accepts values between 0 and 1.\n", STRING(pEntity->GetEntityName()), pEntity->m_flSpeed ); } } } } // Get the waypoints for the next part of the path GetNavigator()->AdvancePath(); if ( !GetNavigator()->GetPath()->GetCurWaypoint() ) { ClearWaypoints(); TaskComplete(); SetGoalEnt( NULL ); return true; } m_vecDesiredPosition = GetNavigator()->GetCurWaypointPos(); CalculatePostPoints(); // Move to the next waypoint delete m_pCurrentWaypoint; m_pCurrentWaypoint = m_pNextWaypoint; m_Waypoints[1] = new CVehicleWaypoint( m_vecPrevPoint, m_vecDesiredPosition, m_vecPostPoint, m_vecPostPostPoint ); m_pNextWaypoint = m_Waypoints[1]; // Drop the spline marker back m_flDistanceAlongSpline = MAX( 0, m_flDistanceAlongSpline - 1.0 ); CheckForTeleport(); return false; }
void CFlexExpresser::InputSpeakResponseConcept( inputdata_t &inputdata ) { const char *pInputString = STRING(inputdata.value.StringID()); // if no params, early out if (!pInputString || *pInputString == 0) { Warning( "empty SpeakResponse input from %s to %s\n", inputdata.pCaller->GetDebugName(), GetDebugName() ); return; } char buf[512]; // temporary for tokenizing char outputmodifiers[512]; // eventual output to speak int outWritten = 0; V_strncpy(buf, pInputString, 510); buf[511] = 0; // just in case the last character is a comma -- enforce that the // last character in the buffer is always a terminator. // special syntax allowing designers to submit inputs with contexts like // "concept,context1:value1,context2:value2,context3:value3" // except that entity i/o seems to eat commas these days (didn't used to be the case) // so instead of commas we have to use spaces in the entity IO, // and turn them into commas here. AWESOME. char *pModifiers = const_cast<char *>(V_strnchr(buf, ' ', 510)); if ( pModifiers ) { *pModifiers = 0; ++pModifiers; // tokenize on spaces char *token = strtok(pModifiers, " "); while (token) { // find the start characters for the key and value // (seperated by a : which we replace with null) char * RESTRICT key = token; char * RESTRICT colon = const_cast<char *>(V_strnchr(key, ':', 510)); char * RESTRICT value; if (!colon) { Warning( "faulty context k:v pair in entity io %s\n", pInputString ); break; } // write the key and colon to the output string int toWrite = colon - key + 1; if ( outWritten + toWrite >= 512 ) { Warning( "Speak input to %s had overlong parameter %s", GetDebugName(), pInputString ); return; } memcpy(outputmodifiers + outWritten, key, toWrite); outWritten += toWrite; *colon = 0; value = colon + 1; // determine if the value is actually a procedural name CBaseEntity *pProcedural = gEntList.FindEntityProcedural( value, this, inputdata.pActivator, inputdata.pCaller ); // write the value to the output -- if it's a procedural name, replace appropriately; // if not, just copy over. const char *valString; if (pProcedural) { valString = STRING(pProcedural->GetEntityName()); } else { valString = value; } toWrite = strlen(valString); toWrite = MIN( 511-outWritten, toWrite ); V_strncpy( outputmodifiers + outWritten, valString, toWrite+1 ); outWritten += toWrite; // get the next token token = strtok(NULL, " "); if (token) { // if there is a next token, write in a comma if (outWritten < 511) { outputmodifiers[outWritten++]=','; } } } } // null terminate just in case outputmodifiers[outWritten] = 0; Speak( buf, outWritten > 0 ? outputmodifiers : NULL ); }
void DrawOverlays(CTFBotMissionSuicideBomber *action, CTFBot *actor) { constexpr float dt = 0.1f; constexpr float target_cross_size = 5.0f; constexpr int target_cross_r = 0x00; constexpr int target_cross_g = 0xff; constexpr int target_cross_b = 0x00; constexpr float det_cross_size = 5.0f; constexpr int det_cross_r = 0xff; constexpr int det_cross_g = 0x00; constexpr int det_cross_b = 0x00; int line; char buf[1024]; /* OVERLAYS: BOT */ line = 0; auto pos = actor->GetAbsOrigin(); snprintf(buf, sizeof(buf), "POS: (%4.0f, %4.0f, %4.0f)", pos.x, pos.y, pos.z); NDebugOverlay::EntityText(ENTINDEX(actor), line++, buf, dt, 255, 255, 255, 255); snprintf(buf, sizeof(buf), "HEALTH: %d", actor->GetHealth()); NDebugOverlay::EntityText(ENTINDEX(actor), line++, buf, dt, 255, 255, 255, 255); CBaseEntity *target = action->m_hTarget; if (target == nullptr) { snprintf(buf, sizeof(buf), "TARGET: null"); } else { const char *name; if (target->IsPlayer()) { name = static_cast<CBasePlayer *>(target)->GetPlayerName(); } else { name = STRING(target->GetEntityName()); } snprintf(buf, sizeof(buf), "TARGET: #%d '%s' '%s'", ENTINDEX(target), target->GetClassname(), name); } NDebugOverlay::EntityText(ENTINDEX(actor), line++, buf, dt, 255, 255, 255, 255); snprintf(buf, sizeof(buf), "PATH FAILS: %d", action->m_nConsecutivePathFailures); NDebugOverlay::EntityText(ENTINDEX(actor), line++, buf, dt, 255, 255, 255, 255); if (action->m_ctRecomputePath.HasStarted()) { snprintf(buf, sizeof(buf), "TIMER(path): %.1f / %.1f", action->m_ctRecomputePath.GetElapsedTime(), action->m_ctRecomputePath.GetCountdownDuration()); } else { snprintf(buf, sizeof(buf), "TIMER(path): NOT STARTED"); } NDebugOverlay::EntityText(ENTINDEX(actor), line++, buf, dt, 255, 255, 255, 255); if (action->m_ctPlaySound.HasStarted()) { snprintf(buf, sizeof(buf), "TIMER(sound): %.1f / %.1f", action->m_ctPlaySound.GetElapsedTime(), action->m_ctPlaySound.GetCountdownDuration()); } else { snprintf(buf, sizeof(buf), "TIMER(sound): NOT STARTED"); } NDebugOverlay::EntityText(ENTINDEX(actor), line++, buf, dt, 255, 255, 255, 255); if (action->m_ctDetonation.HasStarted()) { snprintf(buf, sizeof(buf), "TIMER(det): %.1f / %.1f", action->m_ctDetonation.GetElapsedTime(), action->m_ctDetonation.GetCountdownDuration()); } else { snprintf(buf, sizeof(buf), "TIMER(det): NOT STARTED"); } NDebugOverlay::EntityText(ENTINDEX(actor), line++, buf, dt, 255, 255, 255, 255); snprintf(buf, sizeof(buf), "DETONATING: %s", (action->m_bDetonating ? "yes" : "no")); NDebugOverlay::EntityText(ENTINDEX(actor), line++, buf, dt, 255, 255, 255, 255); snprintf(buf, sizeof(buf), "DET(reached_goal): %s", (action->m_bDetReachedGoal ? "yes" : "no")); NDebugOverlay::EntityText(ENTINDEX(actor), line++, buf, dt, 255, 255, 255, 255); snprintf(buf, sizeof(buf), "DET(lost_all_health): %s", (action->m_bDetLostAllHealth ? "yes" : "no")); NDebugOverlay::EntityText(ENTINDEX(actor), line++, buf, dt, 255, 255, 255, 255); ConVarRef tf_bot_suicide_bomb_range("tf_bot_suicide_bomb_range"); float det_range = tf_bot_suicide_bomb_range.GetFloat() / 3.0f; int det_sphere_r = 0xff; int det_sphere_g = 0x00; int det_sphere_b = 0x00; int det_sphere_a = 0x00; if (action->m_vecTargetPos.DistToSqr(actor->GetAbsOrigin()) < det_range * det_range) { Vector vec_clear = action->m_vecTargetPos; vec_clear.z += 18.0f; if (actor->IsLineOfFireClear(vec_clear)) { det_sphere_r = 0x00; det_sphere_g = 0xff; det_sphere_b = 0x00; } else { det_sphere_r = 0xff; det_sphere_g = 0xff; det_sphere_b = 0x00; } } NDebugOverlay::Sphere(actor->GetAbsOrigin(), vec3_angle, det_range, det_sphere_r, det_sphere_g, det_sphere_b, det_sphere_a, true, dt); /* OVERLAYS: TARGET POS */ line = 0; snprintf(buf, sizeof(buf), "TARGET POS: (%4.0f, %4.0f, %4.0f)", action->m_vecTargetPos.x, action->m_vecTargetPos.y, action->m_vecTargetPos.z); NDebugOverlay::EntityTextAtPosition(action->m_vecTargetPos, line++, buf, dt, 255, 255, 255, 255); snprintf(buf, sizeof(buf), "DIST TO: %.1f", action->m_vecTargetPos.DistToSqr(actor->GetAbsOrigin())); NDebugOverlay::Cross3D(action->m_vecTargetPos, target_cross_size, target_cross_r, target_cross_g, target_cross_b, true, dt); /* OVERLAYS: DETONATE POS */ line = 0; snprintf(buf, sizeof(buf), "DET POS: (%4.0f, %4.0f, %4.0f)", action->m_vecDetonatePos.x, action->m_vecDetonatePos.y, action->m_vecDetonatePos.z); NDebugOverlay::EntityTextAtPosition(action->m_vecDetonatePos, line++, buf, dt, 255, 255, 255, 255); NDebugOverlay::Cross3D(action->m_vecDetonatePos, det_cross_size, det_cross_r, det_cross_g, det_cross_b, true, dt); }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CAI_SpeechFilter::PopulateSubjectList( bool purge ) { // Populate the subject list. Try targetname first. CBaseEntity *pSearch = NULL; int iNumSubjects = 0; do { pSearch = gEntList.FindEntityByName( pSearch, m_iszSubject ); if ( pSearch ) { #ifndef CSTRIKE_DLL CAI_PlayerAlly *pAlly = dynamic_cast<CAI_PlayerAlly *>(pSearch); if ( pAlly ) { if( purge ) { pAlly->SetSpeechFilter( NULL ); } else { if( pAlly->GetSpeechFilter() != NULL ) { DevWarning("ai_speechfilter %s is slamming NPC %s's current speech filter.\n", STRING(GetEntityName()), STRING(pSearch->GetEntityName()) ); } pAlly->SetSpeechFilter( this ); } } else if ( pSearch->IsNPC() ) { DevWarning("ai_speechfilter %s tries to use %s as a subject, but it's not a talking NPC.\n", STRING(GetEntityName()), STRING(pSearch->GetEntityName()) ); } #endif iNumSubjects++; } } while( pSearch ); if ( !iNumSubjects ) { // No subjects found by targetname! Assume classname. do { pSearch = gEntList.FindEntityByClassname( pSearch, STRING(m_iszSubject) ); if( pSearch ) { #ifndef CSTRIKE_DLL CAI_PlayerAlly *pAlly = dynamic_cast<CAI_PlayerAlly *>(pSearch); if ( pAlly ) { if( purge ) { pAlly->SetSpeechFilter( NULL ); } else { if( pAlly->GetSpeechFilter() != NULL ) { DevWarning("ai_speechfilter %s is slamming NPC %s's current speech filter.\n", STRING(GetEntityName()), STRING(pSearch->GetEntityName()) ); } pAlly->SetSpeechFilter( this ); } } else if ( pSearch->IsNPC() ) { DevWarning("ai_speechfilter %s tries to use %s as a subject, but it's not a talking NPC.\n", STRING(GetEntityName()), STRING(pSearch->GetEntityName()) ); } #endif iNumSubjects++; } } while( pSearch ); } // If the subject list is still empty, we have an error! if ( !iNumSubjects ) { DevMsg( 2, "ai_speechfilter finds no subject(s) called: %s\n", STRING( m_iszSubject ) ); } }
void CASW_Arena::SpawnArenaWave() { if ( !ASWSpawnManager() ) return; if ( ASWGameRules() ) { ASWGameRules()->BroadcastSound( "Spawner.Horde" ); } // find the 4 corridor spawn points CUtlVector<CBaseEntity*> arenaSpawns[4]; int arenaSpawnsUsed[4]; memset( arenaSpawnsUsed, 0, sizeof( arenaSpawnsUsed ) ); CBaseEntity* pEntity = NULL; while ((pEntity = gEntList.FindEntityByClassname( pEntity, "info_target" )) != NULL) { if ( !stricmp( STRING( pEntity->GetEntityName() ), "Spawn_Front" ) ) { arenaSpawns[0].AddToTail( pEntity ); } else if ( !stricmp( STRING( pEntity->GetEntityName() ), "Spawn_Right" ) ) { arenaSpawns[1].AddToTail( pEntity ); } else if ( !stricmp( STRING( pEntity->GetEntityName() ), "Spawn_Below" ) ) { arenaSpawns[2].AddToTail( pEntity ); } else if ( !stricmp( STRING( pEntity->GetEntityName() ), "Spawn_Left" ) ) { arenaSpawns[3].AddToTail( pEntity ); } } Msg( "Found arena spawns: N:%d E:%d S:%d W:%d\n", arenaSpawns[0].Count(), arenaSpawns[1].Count(), arenaSpawns[2].Count(), arenaSpawns[3].Count() ); // decide how many alien types we're going to spawn int iAlienTypes = 2; float fRandom = RandomFloat(); if ( fRandom < 0.1f ) { iAlienTypes = 4; } else if ( fRandom < 0.30f ) { iAlienTypes = 3; } for ( int i=0 ; i<iAlienTypes; i++ ) { // decide on a direction int iDirection = RandomInt( 0, 3 ); // decide on an alien type int iAlienType = RandomInt( 0, m_ArenaAliens.Count() - 1 ); int iQuantity = asw_arena_quantity_scale.GetFloat() * RandomInt( m_ArenaAliens[iAlienType]->m_iQuantityMin, m_ArenaAliens[iAlienType]->m_iQuantityMax ); int iArenaLevel = m_iArenaWave / asw_arena_waves_per_difficulty.GetInt(); iQuantity += iArenaLevel; for ( int k=0 ; k < iQuantity ; k++ ) { if ( arenaSpawnsUsed[iDirection] < arenaSpawns[iDirection].Count() ) { CBaseEntity *pSpawnPoint = arenaSpawns[iDirection][arenaSpawnsUsed[iDirection]]; if ( !pSpawnPoint ) continue; if ( ASWSpawnManager()->SpawnAlienAt( m_ArenaAliens[iAlienType]->m_szAlienClass, pSpawnPoint->GetAbsOrigin(), pSpawnPoint->GetAbsAngles() ) ) { arenaSpawnsUsed[iDirection]++; } } } } m_iArenaWave++; }
//--------------------------------------------------------- // Purpose: See if it is time to poll and do so. // // SOON: We need to load-balance this. //--------------------------------------------------------- void CVisibilityMonitor::FrameUpdatePostEntityThink() { if( gpGlobals->curtime < m_flTimeNextPoll ) return; m_flTimeNextPoll = gpGlobals->curtime + vismon_poll_frequency.GetFloat(); int iDebugging = debug_visibility_monitor.GetInt(); if( m_Entities.Count() > m_iMaxEntitiesPerThink ) m_iMaxEntitiesPerThink = m_Entities.Count(); if( iDebugging > 1 ) { Msg("\nVisMon: Polling now. (Frequency: %f)\n", m_flPollFrequency ); Msg("VisMon: Time: %f - Tracking %d Entities. (Max:%d)\n", gpGlobals->curtime, m_Entities.Count(), m_iMaxEntitiesPerThink ); } // Cleanup, dump entities that have been removed since we last polled. for ( int i = 0 ; i < m_Entities.Count() ; i++ ) { if ( m_Entities[i].entity == NULL ) { m_Entities.FastRemove(i); if ( i >= m_Entities.Count() ) { break; } } } int numTraces = 0; bool bHitTraceLimit = false; if( m_iStartElement >= m_Entities.Count() ) { if( iDebugging > 1 ) { Msg("VisMon: RESET\n"); } m_iStartElement = 0; } if( iDebugging > 1 ) { Msg("VisMon: Starting at element: %d\n", m_iStartElement ); } for( int i = m_iStartElement ; i < m_Entities.Count() ; i++ ) { for( int j = 1 ; j <= gpGlobals->maxClients ; j++ ) { CBasePlayer *pPlayer =UTIL_PlayerByIndex( j ); if( pPlayer != NULL && pPlayer->IsAlive() && !pPlayer->IsBot() ) { int memoryBit = 1 << j; // The bit that is used to remember whether a given entity has been seen by a given player. CBaseEntity *pSeeEntity = m_Entities[ i ].entity.Get(); if( pSeeEntity == NULL ) { continue; } if( !(m_Entities[i].memory & memoryBit) ) { // If this player hasn't seen this entity yet, check it. if( EntityIsVisibleToPlayer( m_Entities[i], pPlayer, &numTraces ) ) { bool bIgnore = false; if( m_Entities[i].pfnEvaluator != NULL && !m_Entities[i].pfnEvaluator( m_Entities[i].entity, pPlayer ) ) { bIgnore = true; } // See it! Generate our event. if( iDebugging > 0 ) { if( bIgnore ) { Msg("VisMon: Player %s IGNORING VISIBILE Entity: %s\n", pPlayer->GetDebugName(), pSeeEntity->GetDebugName() ); NDebugOverlay::Cross3D( pSeeEntity->WorldSpaceCenter(), 16, 255, 0, 0, false, 10.0f ); } else { Msg("VisMon: Player %s sees Entity: %s\n", pPlayer->GetDebugName(), pSeeEntity->GetDebugName() ); NDebugOverlay::Cross3D( pSeeEntity->WorldSpaceCenter(), 16, 0, 255, 0, false, 10.0f ); } } if( !bIgnore ) { bool bGenerateEvent = true; if( m_Entities[i].pfnCallback != NULL ) { // Make the callback, and let it determine whether to generate the simple event. bGenerateEvent = m_Entities[i].pfnCallback( m_Entities[i].entity, pPlayer ); } if( bGenerateEvent ) { // No callback, generate the generic game event. IGameEvent * event = gameeventmanager->CreateEvent( "entity_visible" ); if ( event ) { event->SetInt( "userid", pPlayer->GetUserID() ); event->SetInt( "subject", pSeeEntity->entindex() ); event->SetString( "classname", pSeeEntity->GetClassname() ); event->SetString( "entityname", STRING( pSeeEntity->GetEntityName() ) ); gameeventmanager->FireEvent( event ); } } // Remember that this entity was visible to the player m_Entities[i].memory |= memoryBit; } } } } } if( numTraces >= vismon_trace_limit.GetInt() ) { if( iDebugging > 1 ) { Msg("VisMon: MAX Traces. Stopping after element %d\n", i ); } m_iStartElement = i + 1; // Pick up here next think. bHitTraceLimit = true; break; } } if( !bHitTraceLimit ) { m_iStartElement = 0; } if( numTraces > m_iMaxTracesPerThink ) m_iMaxTracesPerThink = numTraces; if( iDebugging > 1 ) { Msg("VisMon: %d traces performed during this polling cycle (Max: %d)\n\n", numTraces, m_iMaxTracesPerThink ); } }