//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #include "cbase.h" #include "tf_gamerules.h" #include "entity_bird.h" #include "KeyValues.h" #include "filesystem.h" #include "tf_fx.h" LINK_ENTITY_TO_CLASS( entity_bird, CEntityBird ); #define ENTITYBIRD_MODEL "models/props_forest/bird.mdl" //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CEntityBird::Spawn( void ) { Precache(); BaseClass::Spawn(); SetMoveType( MOVETYPE_NONE ); SetSolid( SOLID_BBOX ); SetModel( ENTITYBIRD_MODEL ); SetSize( -Vector(8,8,0), Vector(8,8,16) ); SetSequence(0); m_takedamage = DAMAGE_YES; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CEntityBird::Precache( void ) { BaseClass::Precache(); // We deliberately allow late precaches here. It'll cause a hitch, but it'll ensure // we don't load the model on any map that doesn't have birds, and we'll make sure // we don't accidentally keep loading it after the birds are supposed to go away. bool bAllowPrecache = CBaseEntity::IsPrecacheAllowed(); CBaseEntity::SetAllowPrecache( true ); PrecacheModel( ENTITYBIRD_MODEL ); CBaseEntity::SetAllowPrecache( bAllowPrecache ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CEntityBird::Touch( CBaseEntity *pOther ) { BaseClass::Touch( pOther ); // If we're touched by anything, we pop! Explode(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int CEntityBird::OnTakeDamage( const CTakeDamageInfo &info ) { Explode(); return 1; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CEntityBird::Explode( void ) { Vector vecOrigin = WorldSpaceCenter(); CPVSFilter filter( vecOrigin ); TE_TFExplosion( filter, 0.0f, vecOrigin, Vector(0,0,1), TF_WEAPON_NONE, 0 ); UTIL_Remove( this ); } //----------------------------------------------------------------------------- // Purpose: Spawn random birds at locations on certain maps. //----------------------------------------------------------------------------- void CEntityBird::SpawnRandomBirds( void ) { const char *pszMapName = STRING( gpGlobals->mapname ); if ( !pszMapName || !pszMapName[0] ) return; KeyValues *pFileKV = new KeyValues( "birds" ); if ( !pFileKV->LoadFromFile( g_pFullFileSystem, "scripts/birds.txt", "MOD" ) ) return; // Build a list of birds in the map already, and make sure we don't spawn any on those spots again CUtlVector vecExistingBirds; CBaseEntity *pBird = gEntList.FindEntityByClassname( NULL, "entity_bird" ); while( pBird ) { vecExistingBirds.AddToTail( pBird->GetAbsOrigin() ); pBird = gEntList.FindEntityByClassname( pBird, "entity_bird" ); } // See if we have an entry for this map KeyValues *pMapKV = pFileKV->FindKey( pszMapName ); if ( pMapKV ) { CUtlVector vecLocations; KeyValues *pkvLoc = pMapKV->GetFirstSubKey(); while ( pkvLoc ) { const char *pszLocation = pkvLoc->GetString(); int iIdx = vecLocations.AddToTail(); UTIL_StringToVector( vecLocations[iIdx].Base(), pszLocation ); pkvLoc = pkvLoc->GetNextKey(); } if ( vecLocations.Count() ) { //int iLocation = RandomInt(0,vecLocations.Count()-1); for ( int i = 0; i < vecLocations.Count(); i++ ) { bool bExists = false; // Make sure there isn't a bird here already FOR_EACH_VEC( vecExistingBirds, iBird ) { if ( vecLocations[i].DistToSqr(vecExistingBirds[iBird]) < (32*32) ) { bExists = true; break; } } if ( !bExists ) { CBaseEntity::Create( "entity_bird", vecLocations[i], QAngle(0,RandomFloat(0,360),0) ); } } } } pFileKV->deleteThis(); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- #define ENTITY_FLYING_BIRD_SPEED_MIN 200 #define ENTITY_FLYING_BIRD_SPEED_MAX 500 //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void SpawnClientsideFlyingBird( Vector &vecSpawn ) { float flyAngle = RandomFloat( -M_PI, M_PI ); float flyAngleRate = RandomFloat( -1.5f, 1.5f ); float accelZ = RandomFloat( 0.5f, 2.0f ); float speed = RandomFloat( ENTITY_FLYING_BIRD_SPEED_MIN, ENTITY_FLYING_BIRD_SPEED_MAX ); float flGlideTime = RandomFloat( 0.25f, 1.0f ); bool bAllowPrecache = CBaseEntity::IsPrecacheAllowed(); CBaseEntity::SetAllowPrecache( true ); CBaseEntity::PrecacheModel( "models/props_forest/dove.mdl" ); CBaseEntity::SetAllowPrecache( bAllowPrecache ); CPVSFilter filter( vecSpawn ); UserMessageBegin( filter, "SpawnFlyingBird" ); WRITE_VEC3COORD( vecSpawn ); WRITE_FLOAT( flyAngle ); WRITE_FLOAT( flyAngleRate ); WRITE_FLOAT( accelZ ); WRITE_FLOAT( speed ); WRITE_FLOAT( flGlideTime ); MessageEnd(); }