bool CAI_BehaviorBase::NotifyChangeBehaviorStatus( bool fCanFinishSchedule ) { bool fInterrupt = GetOuter()->OnBehaviorChangeStatus( this, fCanFinishSchedule ); if ( !GetOuter()->IsInterruptable()) return false; if ( fInterrupt ) { if ( GetOuter()->m_hCine ) { if( GetOuter()->m_hCine->PlayedSequence() ) { DevWarning( "NPC: %s canceled running script %s due to behavior change\n", GetOuter()->GetDebugName(), GetOuter()->m_hCine->GetDebugName() ); } else { DevWarning( "NPC: %s canceled script %s without playing, due to behavior change\n", GetOuter()->GetDebugName(), GetOuter()->m_hCine->GetDebugName() ); } GetOuter()->m_hCine->CancelScript(); } //!!!HACKHACK // this is dirty, but it forces NPC to pick a new schedule next time through. GetOuter()->ClearSchedule( "Changed behavior status" ); } return fInterrupt; }
int CAI_TacticalServices::FindBackAwayNode(const Vector &vecThreat ) { if ( !CAI_NetworkManager::NetworksLoaded() ) { DevWarning( 2, "Graph not ready for FindBackAwayNode!\n" ); return NO_NODE; } int iMyNode = GetPathfinder()->NearestNodeToNPC(); int iThreatNode = GetPathfinder()->NearestNodeToPoint( vecThreat ); if ( iMyNode == NO_NODE ) { DevWarning( 2, "FindBackAwayNode() - %s has no nearest node!\n", GetEntClassname()); return NO_NODE; } if ( iThreatNode == NO_NODE ) { // DevWarning( 2, "FindBackAwayNode() - Threat has no nearest node!\n" ); iThreatNode = iMyNode; // return false; } // A vector pointing to the threat. Vector vecToThreat; vecToThreat = vecThreat - GetLocalOrigin(); // Get my current distance from the threat float flCurDist = VectorNormalize( vecToThreat ); // Check my neighbors to find a node that's further away for (int link = 0; link < GetNetwork()->GetNode(iMyNode)->NumLinks(); link++) { CAI_Link *nodeLink = GetNetwork()->GetNode(iMyNode)->GetLinkByIndex(link); if ( !m_pPathfinder->IsLinkUsable( nodeLink, iMyNode ) ) continue; int destID = nodeLink->DestNodeID(iMyNode); float flTestDist = ( vecThreat - GetNetwork()->GetNode(destID)->GetPosition(GetHullType()) ).Length(); if ( flTestDist > flCurDist ) { // Make sure this node doesn't take me past the enemy's position. Vector vecToNode; vecToNode = GetNetwork()->GetNode(destID)->GetPosition(GetHullType()) - GetLocalOrigin(); VectorNormalize( vecToNode ); if( DotProduct( vecToNode, vecToThreat ) < 0.0 ) { return destID; } } } return NO_NODE; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CAI_Relationship::Spawn() { m_bIsActive = false; if (m_iszSubject == NULL_STRING) { DevWarning("ai_relationship '%s' with no subject specified, removing.\n", GetDebugName()); UTIL_Remove(this); } else if (m_target == NULL_STRING) { DevWarning("ai_relationship '%s' with no target specified, removing.\n", GetDebugName()); UTIL_Remove(this); } }
void CTriggerTeleportEnt::StartTouch(CBaseEntity *pOther) { if (pOther) { BaseClass::StartTouch(pOther); if (!pDestinationEnt) { if (m_target != NULL_STRING) pDestinationEnt = gEntList.FindEntityByName(NULL, m_target, NULL, pOther, pOther); else { DevWarning("CTriggerTeleport cannot teleport, pDestinationEnt and m_target are null!\n"); return; } } if (!PassesTriggerFilters(pOther)) return; if (pDestinationEnt)//ensuring not null { Vector tmp = pDestinationEnt->GetAbsOrigin(); // make origin adjustments. (origin in center, not at feet) tmp.z -= pOther->WorldAlignMins().z; pOther->Teleport(&tmp, m_bResetAngles ? &pDestinationEnt->GetAbsAngles() : NULL, m_bResetVelocity ? &vec3_origin : NULL); AfterTeleport(); } } }
void CTriggerMomentumPush::OnSuccessfulTouch(CBaseEntity *pOther) { if (pOther) { Vector finalVel; if (HasSpawnFlags(SF_PUSH_DIRECTION_AS_FINAL_FORCE)) finalVel = m_vPushDir; else finalVel = m_vPushDir.Normalized() * m_fPushForce; switch (m_iIncrease) { case 0: break; case 1: finalVel += pOther->GetAbsVelocity(); break; case 2: if (finalVel.LengthSqr() < pOther->GetAbsVelocity().LengthSqr()) finalVel = pOther->GetAbsVelocity(); break; case 3: pOther->SetBaseVelocity(finalVel); break; default: DevWarning("CTriggerMomentumPush:: %i not recognised as valid for m_iIncrease", m_iIncrease); break; } pOther->SetAbsVelocity(finalVel); } }
//----------------------------------------------------------------------------- // Purpose: Saves the given entity's keyvalue data for later use by a spawner. // Returns the index into the templates. //----------------------------------------------------------------------------- int Templates_Add(CBaseEntity *pEntity, const char *pszMapData, int nLen) { const char *pszName = STRING(pEntity->GetEntityName()); if ((!pszName) || (!strlen(pszName))) { DevWarning(1, "RegisterTemplateEntity: template entity with no name, class %s\n", pEntity->GetClassname()); return -1; } TemplateEntityData_t *pEntData = (TemplateEntityData_t *)malloc(sizeof(TemplateEntityData_t)); pEntData->pszName = strdup( pszName ); // We may modify the values of the keys in this mapdata chunk later on to fix Entity I/O // connections. For this reason, we need to ensure we have enough memory to do that. int iKeys = MapEntity_GetNumKeysInEntity( pszMapData ); int iExtraSpace = (strlen(ENTITYIO_FIXUP_STRING)+1) * iKeys; // Extra 1 because the mapdata passed in isn't null terminated pEntData->iMapDataLength = nLen + iExtraSpace + 1; pEntData->pszMapData = (char *)malloc( pEntData->iMapDataLength ); memcpy(pEntData->pszMapData, pszMapData, nLen + 1); pEntData->pszMapData[nLen] = '\0'; // We don't alloc these suckers right now because that gives us no time to // tweak them for Entity I/O purposes. pEntData->iszMapData = NULL_STRING; pEntData->bNeedsEntityIOFixup = false; pEntData->pszFixedMapData = NULL; return g_Templates.AddToTail(pEntData); }
//========================================================= // Verifica las condiciones y devuelve si es // conveniente/posible crear un NPC en las coordenadas. //========================================================= bool CSurvivalZombieSpawn::CanMakeNPC(CAI_BaseNPC *pNPC, Vector *pResult) { // Desactivado if ( Disabled || !sv_spawn_zombies.GetBool() ) { UTIL_RemoveImmediate(pNPC); return false; } Vector origin; // Verificamos si es posible crear el NPC en el radio especificado. if ( !CAI_BaseNPC::FindSpotForNPCInRadius(&origin, GetAbsOrigin(), pNPC, SpawnRadius, true) ) { if ( !CAI_BaseNPC::FindSpotForNPCInRadius(&origin, GetAbsOrigin(), pNPC, SpawnRadius, false) ) { DevWarning("[SURVIVAL ZOMBIE MAKER] No se encontro un lugar valido para crear un zombie. \r\n"); UTIL_RemoveImmediate(pNPC); return false; } } // Crear en la misma altura que el spawn (Y así evitamos que se cree por debajo del suelo) origin.z = GetAbsOrigin().z; *pResult = origin; return true; }
//----------------------------------------------------------------------------- // Purpose: Add effect to effects list // Input : *effect - //----------------------------------------------------------------------------- void CEffectsList::AddEffect( CClientSideEffect *effect ) { #if 0 if ( FXCreationAllowed() == false ) { //NOTENOTE: If you've hit this, you may not add a client effect where you have attempted to. // Most often this means that you have added it in an entity's DrawModel function. // Move this to the ClientThink function instead! Assert(0); return; } #endif if ( effect == NULL ) return; if ( m_nEffects >= MAX_EFFECTS ) { DevWarning( 1, "No room for effect %s\n", effect->GetName() ); return; } m_rgEffects[ m_nEffects++ ] = effect; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMaterialSubRect::SetupMaterialVars( void ) { if ( !m_pMaterialPage ) { DevWarning( 1, "CMaterialSubRect::SetupMaterialVars: Invalid Material Page!\n" ); return; } // Ask the material page for its size. int nMaterialPageWidth = m_pMaterialPage->GetMappingWidth(); int nMaterialPageHeight = m_pMaterialPage->GetMappingHeight(); // Normalize the offset and scale. float flOOWidth = 1.0f / static_cast<float>( nMaterialPageWidth ); float flOOHeight = 1.0f / static_cast<float>( nMaterialPageHeight ); // Add 0.5f to push the image "in" by 1/2 a texel, and subtract 1.0f to push it // "in" by 1/2 a texel on the other side. m_vecOffset.x += 1.0f; m_vecOffset.y += 1.0f; m_vecOffset.x *= flOOWidth; m_vecOffset.y *= flOOHeight; m_vecScale.x = ( m_vecSize.x - 2.0f ) * flOOWidth; m_vecScale.y = ( m_vecSize.y - 2.0f ) * flOOHeight; }
//----------------------------------------------------------------------------- // Purpose: Used to iterate all the entities within a sphere. // Input : pStartEntity - // vecCenter - // flRadius - //----------------------------------------------------------------------------- CBaseEntity *CGlobalEntityList::FindEntityInSphere( CBaseEntity *pStartEntity, const Vector &vecCenter, float flRadius ) { const CEntInfo *pInfo = pStartEntity ? GetEntInfoPtr( pStartEntity->GetRefEHandle() )->m_pNext : FirstEntInfo(); for ( ;pInfo; pInfo = pInfo->m_pNext ) { CBaseEntity *ent = (CBaseEntity *)pInfo->m_pEntity; if ( !ent ) { DevWarning( "NULL entity in global entity list!\n" ); continue; } if ( !ent->edict() ) continue; Vector vecRelativeCenter; ent->CollisionProp()->WorldToCollisionSpace( vecCenter, &vecRelativeCenter ); if ( !IsBoxIntersectingSphere( ent->CollisionProp()->OBBMins(), ent->CollisionProp()->OBBMaxs(), vecRelativeCenter, flRadius ) ) continue; return ent; } // nothing found return NULL; }
void CScriptParser::SearchForFiles( const char *szWildcardPath ) { char filePath[FILE_PATH_MAX_LENGTH]; char basePath[FILE_PATH_MAX_LENGTH]; Q_strncpy( basePath, szWildcardPath, FILE_PATH_MAX_LENGTH ); V_StripFilename( basePath ); FileFindHandle_t findHandle; const char *fileName = filesystem->FindFirstEx( szWildcardPath, GetFSSearchPath(), &findHandle ); while ( fileName != NULL ) { Q_ComposeFileName( basePath, fileName, filePath, FILE_PATH_MAX_LENGTH ); if( !ParseFile( filePath ) ) { if ( m_bAlert ) DevWarning( "[script_parser] Unable to parse '%s'!\n", filePath ); } fileName = filesystem->FindNext( findHandle ); } filesystem->FindClose( findHandle ); }
//----------------------------------------------------------------------------- // Purpose: Look through //----------------------------------------------------------------------------- IMaterialVar *CMaterialSubRect::FindVar( char const *varName, bool *found, bool complain ) { // Look for the var in the material page - it has precedence. IMaterialVar *pVar = m_pMaterialPage->FindVar( varName, found, false ); if ( *found ) return pVar; // Look for the var in the local list of vars. MaterialVarSym_t symVar = IMaterialVar::FindSymbol( varName ); if ( symVar != UTL_INVAL_SYMBOL ) { int nVarCount = m_aMaterialVars.Count(); for ( int iVar = 0; iVar < nVarCount; ++iVar ) { if ( m_aMaterialVars[iVar]->GetNameAsSymbol() == symVar ) { *found = true; return m_aMaterialVars[iVar]; } } } // Not found! if( complain ) { static int complainCount = 0; if( complainCount < 100 ) { DevWarning( 1, "No such variable \"%s\" for material \"%s\"\n", varName, GetName() ); complainCount++; } } return GetDummyMaterialVar(); }
//----------------------------------------------------------------------------- // Purpose: Deconstructor //----------------------------------------------------------------------------- CMaterialSubRect::~CMaterialSubRect() { Uncache( ); if( m_nRefCount != 0 ) { DevWarning( 1, "Reference Count for Material %s (%d) != 0\n", GetName(), m_nRefCount ); } if ( m_pMaterialPage ) { m_pMaterialPage->DecrementReferenceCount(); m_pMaterialPage = NULL; } if ( m_pVMTKeyValues ) { m_pVMTKeyValues->deleteThis(); m_pVMTKeyValues = NULL; } m_aMaterialVars.Purge(); #ifdef _DEBUG if ( m_pDebugName ) { delete[] m_pDebugName; m_pDebugName = NULL; } #endif }
//------------------------------------------------------------------------------ // Purpose : Updates network link state if dynamic link state has changed // Input : // Output : //------------------------------------------------------------------------------ void CAI_DynamicLink::SetLinkState(void) { if ( !gm_bInitialized ) { // Safe to quietly return. Consistency will be enforced when InitDynamicLinks() is called return; } if (m_nSrcID == NO_NODE || m_nDestID == NO_NODE) { Vector pos = GetAbsOrigin(); DevWarning("ERROR: Dynamic link at %f %f %f pointing to invalid node ID!!\n", pos.x, pos.y, pos.z); return; } // ------------------------------------------------------------------ // Now update the node links... // Nodes share links so we only have to find the node from the src // For now just using one big AINetwork so find src node on that network // ------------------------------------------------------------------ CAI_Node *pSrcNode = g_pBigAINet->GetNode( m_nSrcID, false ); if ( !pSrcNode ) return; CAI_Link* pLink = FindLink(); if ( !pLink ) { DevMsg("Dynamic Link Error: (%s) unable to form between nodes %d and %d\n", GetDebugName(), m_nSrcID, m_nDestID ); return; } pLink->m_pDynamicLink = this; if (m_nLinkState == LINK_OFF) { pLink->m_LinkInfo |= bits_LINK_OFF; } else { pLink->m_LinkInfo &= ~bits_LINK_OFF; } if ( m_bPreciseMovement ) { pLink->m_LinkInfo |= bits_LINK_PRECISE_MOVEMENT; } else { pLink->m_LinkInfo &= ~bits_LINK_PRECISE_MOVEMENT; } if ( m_nPriority == 0 ) { pLink->m_LinkInfo &= ~bits_PREFER_AVOID; } else { pLink->m_LinkInfo |= bits_PREFER_AVOID; } }
//----------------------------------------------------------------------------- // Purpose: Returns last known posiiton of given enemy //----------------------------------------------------------------------------- const Vector &CAI_Enemies::LastKnownPosition( CBaseEntity *pEnemy ) { static Vector defPos; AI_EnemyInfo_t *pMemory = Find( pEnemy, true ); if ( pMemory ) return pMemory->vLastKnownLocation; DevWarning( 2,"Asking LastKnownPosition for enemy that's not in my memory!!\n"); return defPos; }
//========================================================= //========================================================= float CAnimating::SequenceDuration( CStudioHdr *pStudioHdr, int iSequence ) { if ( !pStudioHdr ) { DevWarning( 2, "CBaseAnimating::SequenceDuration( %d ) NULL pstudiohdr on %s!\n", iSequence, GetClassname() ); return 0.1; } if ( !pStudioHdr->SequencesAvailable() ) { return 0.1; } if (iSequence >= pStudioHdr->GetNumSeq() || iSequence < 0 ) { DevWarning( 2, "CBaseAnimating::SequenceDuration( %d ) out of range\n", iSequence ); return 0.1; } return Studio_Duration( pStudioHdr, iSequence, GetPoseParameterArray() ); }
void CNPC_Crow::StartTargetHandling( CBaseEntity *pTargetEnt ) { AI_NavGoal_t goal( GOALTYPE_PATHCORNER, pTargetEnt->GetAbsOrigin(), ACT_FLY, AIN_DEF_TOLERANCE, AIN_YAW_TO_DEST); if ( !GetNavigator()->SetGoal( goal ) ) { DevWarning( 2, "Can't Create Route!\n" ); } }
// Convenient way to delay removing oneself void CBaseEntity::SUB_Remove( void ) { if (m_iHealth > 0) { // this situation can screw up NPCs who can't tell their entity pointers are invalid. m_iHealth = 0; DevWarning( 2, "SUB_Remove called on entity with health > 0\n"); } UTIL_Remove( this ); }
//----------------------------------------------------------------------------- // Aim the next rocket at a specific target //----------------------------------------------------------------------------- void CPropAPC::InputFireMissileAt( inputdata_t &inputdata ) { string_t strMissileTarget = MAKE_STRING( inputdata.value.String() ); CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, strMissileTarget, NULL, inputdata.pActivator, inputdata.pCaller ); if ( pTarget == NULL ) { DevWarning( "%s: Could not find target '%s'!\n", GetClassname(), STRING( strMissileTarget ) ); return; } m_hSpecificRocketTarget = pTarget; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CHudElement *CHud::FindElement(const char *pName) { for (int i = 0; i < m_HudList.Size(); i++) { if (V_stricmp(m_HudList[i]->GetName(), pName) == 0) return m_HudList[i]; } DevWarning(1, "Could not find Hud Element: %s\n", pName); Assert(0); return NULL; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CHudElement *CHud::FindElement( const char *pName ) { for ( int i = 0; i < GetHudList().Count(); i++ ) { if ( stricmp( GetHudList()[ i ]->GetName(), pName ) == 0 ) return GetHudList()[i]; } DevWarning(1, "[%d] Could not find Hud Element: %s\n", m_nSplitScreenSlot, pName ); Assert(0); return NULL; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMaterialSubRect::ParseMaterialVars( KeyValues &keyValues ) { KeyValues *pKeyValues = &keyValues; // I'm not quite sure how this can happen, but we'll see... const char *pShaderName = pKeyValues->GetName(); if ( !pShaderName ) { DevWarning( 1, "CMaterialSubRect::InitializeShader: Shader not specified in material %s.\n", GetName() ); Assert( 0 ); pShaderName = IsPC() ? "Wireframe_DX6" : "Wireframe_DX9"; } // Verify we have the correct "shader." There is only one type. if ( !Q_strcmp( pShaderName, "Subrect" ) ) { KeyValues *pVar = pKeyValues->GetFirstSubKey(); while ( pVar ) { if ( !Q_strcmp( pVar->GetName(), "$Pos" ) ) { sscanf( pVar->GetString(), "%f %f", &m_vecOffset.x, &m_vecOffset.y ); } if ( !Q_strcmp( pVar->GetName(), "$Size" ) ) { sscanf( pVar->GetString(), "%f %f", &m_vecSize.x, &m_vecSize.y ); } if ( !Q_strcmp( pVar->GetName(), "$Material" ) ) { m_pMaterialPage = static_cast<IMaterialInternal*>( MaterialSystem()->FindMaterial( pVar->GetString(), TEXTURE_GROUP_DECAL ) ); m_pMaterialPage = m_pMaterialPage->GetRealTimeVersion(); //always work with the realtime material internally } // if ( !Q_strcmp( pVar->GetName(), "$decalscale" ) ) // { // m_flDecalScale = pVar->GetFloat(); // } // Add var to list. IMaterialVar *pNewVar = CreateMaterialVarFromKeyValue( this, pVar ); if ( pNewVar ) { m_aMaterialVars.AddToTail( pNewVar ); } // Continue getting the keys until they are all found. pVar = pVar->GetNextKey(); } } }
//----------------------------------------------------------------------------- // Purpose: Returns the last position the enemy was SEEN at. This will always be // different than LastKnownPosition() when the enemy is out of sight, because // the last KNOWN position will be updated for a number of seconds after the // player disappears. //----------------------------------------------------------------------------- const Vector &CAI_Enemies::LastSeenPosition( CBaseEntity *pEnemy ) { AI_EnemyInfo_t *pMemory = Find( pEnemy, true ); if ( pMemory ) { m_vecDefaultLSP = pMemory->vLastSeenLocation; } else { DevWarning( 2,"Asking LastSeenPosition for enemy that's not in my memory!!\n"); } return m_vecDefaultLSP; }
//----------------------------------------------------------------------------- // Purpose: Sets position to the last known position of an enemy. If enemy // was not found returns last memory of danger position if it exists // Output : Returns false is no position is known //----------------------------------------------------------------------------- float CAI_Enemies::LastTimeSeen( CBaseEntity *pEnemy) { // I've never seen something that doesn't exist if (!pEnemy) return 0; AI_EnemyInfo_t *pMemory = Find( pEnemy, true ); if ( pMemory ) return pMemory->flLastTimeSeen; DevWarning( 2,"Asking LastTimeSeen for enemy that's not in my memory!!\n"); return 0; }
void CTriggerTimerStop::StartTouch(CBaseEntity *pOther) { ConVarRef cheatsRef("sv_cheats"); BaseClass::StartTouch(pOther); // If timer is already stopped, there's nothing to stop (No run state effect to play) if (pOther->IsPlayer() && g_Timer.IsRunning()) { if (!cheatsRef.GetBool()) g_Timer.Stop(true); else DevWarning("You must turn off cheats to use the timer!\n"); } }
//----------------------------------------------------------------------------- // Purpose: The act has finished //----------------------------------------------------------------------------- void CInfoAct::FinishAct( ) { if ( g_hCurrentAct.Get() != this ) { DevWarning( 2, "Attempted to finish an act which wasn't started!\n" ); return; } ShutdownRespawnTimers(); switch( m_iWinners) { case 0: m_OnFinishedTeamNone.FireOutput( this, this ); break; case 1: m_OnFinishedTeam1.FireOutput( this, this ); break; case 2: m_OnFinishedTeam2.FireOutput( this, this ); break; default: Assert(0); break; } g_hCurrentAct = NULL; // Tell all the clients CRelieableBroadcastRecipientFilter filter; UserMessageBegin( filter, "ActEnd" ); WRITE_BYTE( m_iWinners ); MessageEnd(); // Am I an intermission? if ( HasSpawnFlags( SF_ACT_INTERMISSION ) ) { // Cycle through all players and end the intermission for them for ( int i = 1; i <= gpGlobals->maxClients; i++ ) { CBaseTFPlayer *pPlayer = (CBaseTFPlayer*)UTIL_PlayerByIndex( i ); if ( pPlayer ) { EndIntermission( pPlayer ); } } } }
//----------------------------------------------------------------------------- // Purpose: // Input : *pEvent - // *pOperator - //----------------------------------------------------------------------------- void CBaseCombatWeapon::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) { if ( (pEvent->type & AE_TYPE_NEWEVENTSYSTEM) && (pEvent->type & AE_TYPE_SERVER) ) { if ( pEvent->event == AE_NPC_WEAPON_FIRE ) { bool bSecondary = (atoi( pEvent->options ) != 0); Operator_ForceNPCFire( pOperator, bSecondary ); return; } } DevWarning( 2, "Unhandled animation event %d from %s --> %s\n", pEvent->event, pOperator->GetClassname(), GetClassname() ); }
//----------------------------------------------------------------------------- float CAI_Enemies::LastTimeTookDamageFrom( CBaseEntity *pEnemy) { // I've never seen something that doesn't exist if (!pEnemy) return 0; AI_EnemyInfo_t *pMemory = Find( pEnemy, true ); if ( pMemory ) return pMemory->timeLastReceivedDamageFrom; if ( pEnemy != AI_UNKNOWN_ENEMY ) DevWarning( 2,"Asking LastTimeTookDamageFrom for enemy that's not in my memory!!\n"); return AI_INVALID_TIME; }
//----------------------------------------------------------------------------- // Purpose: Sets position to the last known position of an enemy. If enemy // was not found returns last memory of danger position if it exists // Output : Returns false is no position is known //----------------------------------------------------------------------------- float CAI_Enemies::LastTimeSeen( CBaseEntity *pEnemy, bool bCheckDangerMemory /*= true*/ ) { // I've never seen something that doesn't exist if (!pEnemy) return 0; AI_EnemyInfo_t *pMemory = Find( pEnemy, bCheckDangerMemory ); if ( pMemory ) return pMemory->timeLastSeen; if ( pEnemy != AI_UNKNOWN_ENEMY ) DevWarning( 2,"Asking LastTimeSeen for enemy that's not in my memory!!\n"); return AI_INVALID_TIME; }
//----------------------------------------------------------------------------- // Purpose: Returns the time at which the enemy was first seen firsthand // Input : *pEnemy - // Output : float //----------------------------------------------------------------------------- float CAI_Enemies::TimeAtFirstHand( CBaseEntity *pEnemy ) { // I've never seen something that doesn't exist if (!pEnemy) return 0; AI_EnemyInfo_t *pMemory = Find( pEnemy, true ); if ( pMemory ) return pMemory->timeAtFirstHand; if ( pEnemy != AI_UNKNOWN_ENEMY ) DevWarning( 2,"Asking TimeAtFirstHand for enemy that's not in my memory!!\n"); return AI_INVALID_TIME; }