Пример #1
0
//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
Vector CAI_BaseFlyingBot::VelocityToAvoidObstacles(float flInterval)
{
	// --------------------------------
	//  Avoid banging into stuff
	// --------------------------------
	trace_t tr;
	Vector vTravelDir = m_vCurrentVelocity*flInterval;
	Vector endPos = GetAbsOrigin() + vTravelDir;
	AI_TraceEntity( this, GetAbsOrigin(), endPos, GetAITraceMask()|CONTENTS_WATER, &tr );
	if (tr.fraction != 1.0)
	{	
		// Bounce off in normal 
		Vector vBounce = tr.plane.normal * 0.5 * m_vCurrentVelocity.Length();
		return (vBounce);
	}
	
	// --------------------------------
	// Try to remain above the ground.
	// --------------------------------
	float flMinGroundDist = MinGroundDist();
	AI_TraceLine(GetAbsOrigin(), GetAbsOrigin() + Vector(0, 0, -flMinGroundDist), 
		GetAITraceMask_BrushOnly()|CONTENTS_WATER, this, COLLISION_GROUP_NONE, &tr);
	if (tr.fraction < 1)
	{
		// Clamp veloctiy
		if (tr.fraction < 0.1)
		{
			tr.fraction = 0.1;
		}

		return Vector(0, 0, 50/tr.fraction);
	}
	return vec3_origin;
}
Пример #2
0
//-----------------------------------------------------------------------------
// Purpose: Input handler that makes the crow fly away.
//-----------------------------------------------------------------------------
void CNPC_Crow::InputFlyAway( inputdata_t &inputdata )
{
	string_t sTarget = MAKE_STRING( inputdata.value.String() );

	if ( sTarget != NULL_STRING )// this npc has a target
	{
		CBaseEntity *pEnt = gEntList.FindEntityByName( NULL, sTarget );

		if ( pEnt )
		{
			trace_t tr;
			AI_TraceLine ( EyePosition(), pEnt->GetAbsOrigin(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr );

			if ( tr.fraction != 1.0f )
				 return;

			// Find the npc's initial target entity, stash it
			SetGoalEnt( pEnt );
		}
	}
	else
		SetGoalEnt( NULL );

	SetCondition( COND_CROW_FORCED_FLY );
	SetCondition( COND_PROVOKED );

}
Пример #3
0
//------------------------------------------------------------------------------
// Computes the spotlight endpoint
//------------------------------------------------------------------------------
void CAI_Spotlight::ComputeEndpoint( const Vector &vecStartPoint, Vector *pEndPoint )
{
	// Create the endpoint
	trace_t tr;
	AI_TraceLine( vecStartPoint, vecStartPoint + m_vSpotlightDir * 2 * m_flSpotlightMaxLength, MASK_OPAQUE, GetOuter(), COLLISION_GROUP_NONE, &tr );
	*pEndPoint = tr.endpos;
}
Пример #4
0
int CASW_Parasite::RangeAttack1Conditions( float flDot, float flDist )
{
	if ( gpGlobals->curtime < m_flNextAttack )
		return 0;

	if ( ( GetFlags() & FL_ONGROUND ) == false )
		return 0;

	// This code stops lots of headcrabs swarming you and blocking you
	// whilst jumping up and down in your face over and over. It forces
	// them to back up a bit. If this causes problems, consider using it
	// for the fast headcrabs only, rather than just removing it.(sjb)
	if ( flDist < ASW_PARASITE_MIN_JUMP_DIST )
		return COND_TOO_CLOSE_TO_ATTACK;

	if ( flDist > ASW_PARASITE_MAX_JUMP_DIST )
		return COND_TOO_FAR_TO_ATTACK;

	// Make sure the way is clear!
	CBaseEntity *pEnemy = GetEnemy();
	if( pEnemy )
	{
		bool bEnemyIsBullseye = ( dynamic_cast<CNPC_Bullseye *>(pEnemy) != NULL );

		trace_t tr;
		AI_TraceLine( EyePosition(), pEnemy->EyePosition(), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );

		if ( tr.m_pEnt != GetEnemy() )
		{
			if ( !bEnemyIsBullseye || tr.m_pEnt != NULL )
				return COND_NONE;
		}

		if( GetEnemy()->EyePosition().z - 36.0f > GetAbsOrigin().z )
		{
			// Only run this test if trying to jump at a player who is higher up than me, else this 
			// code will always prevent a headcrab from jumping down at an enemy, and sometimes prevent it
			// jumping just slightly up at an enemy.
			Vector vStartHullTrace = GetAbsOrigin();
			vStartHullTrace.z += 1.0;

			Vector vEndHullTrace = GetEnemy()->EyePosition() - GetAbsOrigin();
			vEndHullTrace.NormalizeInPlace();
			vEndHullTrace *= 8.0;
			vEndHullTrace += GetAbsOrigin();

			AI_TraceHull( vStartHullTrace, vEndHullTrace,GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, GetCollisionGroup(), &tr );

			if ( tr.m_pEnt != NULL && tr.m_pEnt != GetEnemy() )
			{
				return COND_TOO_CLOSE_TO_ATTACK;
			}
		}
	}

	return COND_CAN_RANGE_ATTACK1;
}
Пример #5
0
void C_ASW_Sentry_Top::AdjustRadiusBeamEdges( const Vector &vecStart, const Vector &vecDir, int iControlPoint )
{
	CTraceFilterSkipTwoEntities traceFilter( this, GetSentryBase(), COLLISION_GROUP_DEBRIS );

	trace_t tr;
	AI_TraceLine( vecStart, vecStart + vecDir * 500.0f, MASK_SHOT, &traceFilter, &tr );

	m_hRadiusDisplay->SetControlPoint( iControlPoint, tr.endpos );
}
Пример #6
0
//----------------------------------------------------------------------------------
// Purpose: Returns z value of floor below given point (up to fMaxDrop inches below)
// Input  :
// Output :
//----------------------------------------------------------------------------------
float GetFloorZ(const Vector &origin, float fMaxDrop) 
{
	// trace to the ground, then pop up 8 units and place node there to make it
	// easier for them to connect (think stairs, chairs, and bumps in the floor).
	// After the routing is done, push them back down.
	//
	trace_t	tr;
	AI_TraceLine ( origin,
					 origin - Vector ( 0, 0, fMaxDrop ),
					 MASK_NPCSOLID_BRUSHONLY,
					 NULL,
					 COLLISION_GROUP_NONE, 
					 &tr );

	// This trace is ONLY used if we hit an entity flagged with FL_WORLDBRUSH
	trace_t	trEnt;
	AI_TraceLine ( origin,
					 origin - Vector ( 0, 0, fMaxDrop ),
					 MASK_NPCSOLID,
					 NULL,
					 COLLISION_GROUP_NONE, 
					 &trEnt );

	
	// Did we hit something closer than the floor?
	if ( trEnt.fraction < tr.fraction )
	{
		// If it was a world brush entity, copy the node location
		if ( trEnt.m_pEnt )
		{
			CBaseEntity *e = trEnt.m_pEnt;
			if ( e && ( e->GetFlags() & FL_WORLDBRUSH ) )
			{
				tr.endpos = trEnt.endpos;
			}
		}
	}

	return tr.endpos.z;
}
Пример #7
0
void CNPC_Stalker::UpdateAttackBeam( void )
{
	CBaseEntity *pEnemy = GetEnemy();
	// If not burning at a target 
	if (pEnemy)
	{
		if (gpGlobals->curtime > m_fBeamEndTime)
		{
			TaskComplete();
		}
		else 
		{
			Vector enemyLKP = GetEnemyLKP();
			m_vLaserTargetPos = enemyLKP + pEnemy->GetViewOffset();

			// Face my enemy
			GetMotor()->SetIdealYawToTargetAndUpdate( enemyLKP );

			// ---------------------------------------------
			//	Get beam end point
			// ---------------------------------------------
			Vector vecSrc = LaserStartPosition(GetAbsOrigin());
			Vector targetDir = m_vLaserTargetPos - vecSrc;
			VectorNormalize(targetDir);
			// --------------------------------------------------------
			//	If beam position and laser dir are way off, end attack
			// --------------------------------------------------------
			if ( DotProduct(targetDir,m_vLaserDir) < 0.5 )
			{
				TaskComplete();
				return;
			}

			trace_t tr;
			AI_TraceLine( vecSrc, vecSrc + m_vLaserDir * MAX_STALKER_FIRE_RANGE, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr);
			// ---------------------------------------------
			//  If beam not long enough, stop attacking
			// ---------------------------------------------
			if (tr.fraction == 1.0)
			{
				TaskComplete();
				return;
			}

			CSoundEnt::InsertSound(SOUND_DANGER, tr.endpos, 60, 0.025, this);
		}
	}
	else
	{
		TaskFail(FAIL_NO_ENEMY);
	}
}
//=========================================================
// FVisible - returns true if a line can be traced from
// the caller's eyes to the target vector
//=========================================================
bool CNPC_Bullsquid::FVisible ( Vector vecOrigin )
{
	trace_t tr;
	Vector		vecLookerOrigin;
	
	vecLookerOrigin = EyePosition();//look through the caller's 'eyes'
	AI_TraceLine(vecLookerOrigin, vecOrigin, MASK_OPAQUE, this/*pentIgnore*/, COLLISION_GROUP_NONE, &tr);
	
	if ( tr.fraction != 1.0 )
		 return false; // Line of sight is not established
	else
		 return true;// line of sight is valid.
}
Пример #9
0
//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
bool CNPC_EnemyFinder::FVisible( CBaseEntity *pTarget, int traceMask, CBaseEntity **ppBlocker )
{
	float flTargetDist = GetAbsOrigin().DistTo( pTarget->GetAbsOrigin() );
	if ( flTargetDist < m_flMinSearchDist)
		return false;

	if ( m_flMaxSearchDist && flTargetDist > m_flMaxSearchDist)
		return false;

	if ( !FBitSet( m_spawnflags, SF_ENEMY_FINDER_CHECK_VIS) )
		return true;

	if ( !HasSpawnFlags(SF_ENEMY_FINDER_APC_VIS) )
	{
		bool bIsVisible = BaseClass::FVisible( pTarget, traceMask, ppBlocker );
		
		if ( bIsVisible && pTarget == m_PlayerFreePass.GetPassTarget() )
			bIsVisible = m_PlayerFreePass.ShouldAllowFVisible( bIsVisible );

		return bIsVisible;
	}

	// Make sure I can see the target from my position
	trace_t tr;

	// Trace from launch position to target position.  
	// Use position above actual barral based on vertical launch speed
	Vector vStartPos = GetAbsOrigin();
	Vector vEndPos	 = pTarget->EyePosition();

	CBaseEntity *pVehicle = NULL;
	if ( pTarget->IsPlayer() )
	{
		CBasePlayer *pPlayer = assert_cast<CBasePlayer*>(pTarget);
		pVehicle = pPlayer->GetVehicleEntity();
	}

	CTraceFilterSkipTwoEntities traceFilter( pTarget, pVehicle, COLLISION_GROUP_NONE );
	AI_TraceLine( vStartPos, vEndPos, MASK_SHOT, &traceFilter, &tr );
	if ( ppBlocker )
	{
		*ppBlocker = tr.m_pEnt;
	}
	return (tr.fraction == 1.0);
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
bool CDarknessLightSourcesSystem::AreThereLightSourcesWithinRadius( CBaseEntity *pLooker, float flRadius )
{
	float flRadiusSqr = (flRadius * flRadius);
	for ( int i = m_LightSources.Count() - 1; i >= 0; i-- )
	{
		// Removed?
		if ( m_LightSources[i].hEntity == NULL || m_LightSources[i].hEntity->IsMarkedForDeletion() )
		{
			m_LightSources.FastRemove( i );
			continue;
		}

		CBaseEntity *pLightSource = m_LightSources[i].hEntity;

		// Close enough to a light source?
		float flDistanceSqr = (pLooker->WorldSpaceCenter() - pLightSource->GetAbsOrigin()).LengthSqr();
		if ( flDistanceSqr < flRadiusSqr )
		{
			trace_t tr;
			AI_TraceLine( pLooker->EyePosition(), pLightSource->GetAbsOrigin(), MASK_SOLID_BRUSHONLY, pLooker, COLLISION_GROUP_NONE, &tr );

			if ( g_debug_darkness.GetBool() )
			{
				if (tr.fraction != 1.0)
				{
					NDebugOverlay::Line( pLooker->WorldSpaceCenter(), tr.endpos, 255,0,0,true, 0.1);
				}
				else
				{
					NDebugOverlay::Line( pLooker->WorldSpaceCenter(), tr.endpos, 0,255,0,true, 0.1);
					NDebugOverlay::Line( pLightSource->GetAbsOrigin(), tr.endpos, 255,0,0,true, 0.1);
				}
			}

			if ( tr.fraction == 1.0 )
				return true;
		}
	}

	return false;
}
Пример #11
0
//---------------------------------------------------------
//---------------------------------------------------------
bool CNPC_Roller::IsBlocked( const Vector &vecCheck )
{
	trace_t tr;

	return false;

#if 0
	NDebugOverlay::Line( GetLocalOrigin(), GetLocalOrigin() + vecCheck, 255,255,0, true, 0.1 );
	
	Vector vecRight;
	Vector vecForward;

	AngleVectors( GetLocalAngles(), &vecForward, &vecRight, NULL );

	NDebugOverlay::Line( GetLocalOrigin() + vecRight * 32, GetLocalOrigin() + vecRight * -32, 0,255,0, true, 0.1 );

#endif ROLLER_DEBUG

	AI_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vecCheck, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
	return ( tr.fraction != 1.0 );
}
Пример #12
0
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CNPC_GroundTurret::ProjectBeam( const Vector &vecStart, const Vector &vecDir, int width, int brightness, float duration )
{
	CBeam *pBeam;
	pBeam = CBeam::BeamCreate( GROUNDTURRET_BEAM_SPRITE, width );
	if ( !pBeam )
		return;

	trace_t tr;
	AI_TraceLine( vecStart, vecStart + vecDir * m_flSensingDist, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
	
	pBeam->SetStartPos( tr.endpos );
	pBeam->SetEndPos( tr.startpos );
	pBeam->SetWidth( width );
	pBeam->SetEndWidth( 0.1 );
	pBeam->SetFadeLength( 16 );

	pBeam->SetBrightness( brightness );
	pBeam->SetColor( 0, 145+random->RandomInt( -16, 16 ), 255 );
	pBeam->RelinkBeam();
	pBeam->LiveForTime( duration );
}
Пример #13
0
//------------------------------------------------------------------------------
// Purpose : Override base implimentation to let decals pass through
//			 me onto the surface beneath
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CNPC_Bullseye::DecalTrace( trace_t *pOldTrace, char const *decalName )
{
	int index = decalsystem->GetDecalIndexForName( decalName );
	if ( index < 0 )
		return;

	// Get direction of original trace
	Vector vTraceDir = pOldTrace->endpos - pOldTrace->startpos;
	VectorNormalize(vTraceDir);

	// Create a new trace that passes through me
	Vector vStartTrace	= pOldTrace->endpos - (1.0 * vTraceDir);
	Vector vEndTrace	= pOldTrace->endpos + (MAX_TRACE_LENGTH * vTraceDir);

	trace_t pNewTrace;
	AI_TraceLine(vStartTrace, vEndTrace, MASK_SHOT, this, COLLISION_GROUP_NONE, &pNewTrace);

	CBroadcastRecipientFilter filter;
	te->Decal( filter, 0.0, &pNewTrace.endpos, &pNewTrace.startpos,
		ENTINDEX( pNewTrace.m_pEnt ), pNewTrace.hitbox, index );
}
Пример #14
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CNPC_Bullseye::ImpactTrace( trace_t *pTrace, int iDamageType, char *pCustomImpactName )
{
	// Get direction of original trace
	Vector vTraceDir = pTrace->endpos - pTrace->startpos;
	VectorNormalize(vTraceDir);

	// Create a new trace that passes through me
	Vector vStartTrace	= pTrace->endpos - (1.0 * vTraceDir);
	Vector vEndTrace	= pTrace->endpos + (MAX_TRACE_LENGTH * vTraceDir);

	trace_t pNewTrace;
	AI_TraceLine(vStartTrace, vEndTrace, MASK_SHOT, this, COLLISION_GROUP_NONE, &pNewTrace);

	CBaseEntity	*pEntity = pNewTrace.m_pEnt;

	// Only do this for BSP model entities
	if ( ( pEntity ) && ( pEntity->IsBSPModel() == false ) )
		return;

	BaseClass::ImpactTrace( pTrace, iDamageType, pCustomImpactName );
}
Пример #15
0
//-----------------------------------------------------------------------------
// Purpose: Override so can handle LOS to m_pScriptedTarget
// Input  :
// Output :
//-----------------------------------------------------------------------------
bool CNPC_Stalker::InnateWeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions )
{
	// --------------------
	// Check for occlusion
	// --------------------
	// Base class version assumes innate weapon position is at eye level
	Vector barrelPos = LaserStartPosition(ownerPos);
	trace_t tr;
	AI_TraceLine( barrelPos, targetPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr);

	if ( tr.fraction == 1.0 )
	{
		return true;
	}

	CBaseEntity *pBE = tr.m_pEnt;
	CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pBE );
	if ( pBE == GetEnemy() )
	{
		return true;
	}
	else if (pBCC) 
	{
		if (IRelationType( pBCC ) == D_HT)
		{
			return true;
		}
		else if (bSetConditions)
		{
			SetCondition(COND_WEAPON_BLOCKED_BY_FRIEND);
		}
	}
	else if (bSetConditions)
	{
		SetCondition(COND_WEAPON_SIGHT_OCCLUDED);
		SetEnemyOccluder(pBE);
	}

	return false;
}
// Эффект пыли для шагов крематора (аналогично шагам страйдера или охотника, но в меньших масштабах
void CNPC_Cremator::FootstepEffect( const Vector &origin )
{
	trace_t tr;
	AI_TraceLine( origin, origin - Vector(0,0,0), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
	float yaw = random->RandomInt(0,0);
	for ( int i = 0; i < 2; i++ )
	{
		if ( UTIL_PointContents( tr.endpos + Vector( 0, 0, 1 ) ) & MASK_WATER )
		{
			float flWaterZ = UTIL_FindWaterSurface( tr.endpos, tr.endpos.z, tr.endpos.z + 100.0f );

			CEffectData	data;
			data.m_fFlags = 0;
			data.m_vOrigin = tr.endpos;
			data.m_vOrigin.z = flWaterZ;
			data.m_vNormal = Vector( 0, 0, 1 );
			data.m_flScale = random->RandomFloat( 10.0, 14.0 );

			// Если крематор идет по неглубокой воде, образуются всплески.
			DispatchEffect( "watersplash", data );
		}
		
		else
		{
			Vector dir = UTIL_YawToVector( yaw + i*180 ) * 10;
			VectorNormalize( dir );
			dir.z = 0.25;
			VectorNormalize( dir );
			g_pEffects->Dust( tr.endpos, dir, 12, 50 );

			/*g_pEffects->FootprintDecal( tr.endpos, dir, 12, 50 );

			virtual void FootprintDecal( IRecipientFilter& filer, float delay, const Vector *origin, const Vector* right, 
		int entity, int index, unsigned char materialType ) = 0;
			virtual void Dust( IRecipientFilter& filer, float delay,
				 const Vector &pos, const Vector &dir, float size, float speed ) = 0;*/
		}
	}
}
Пример #17
0
void CASW_Alien_Jumper::CreateDust( bool placeDecal )
{
	trace_t	tr;
	AI_TraceLine( GetAbsOrigin()+Vector(0,0,1), GetAbsOrigin()-Vector(0,0,64), MASK_SOLID_BRUSHONLY | CONTENTS_PLAYERCLIP | CONTENTS_MONSTERCLIP, this, COLLISION_GROUP_NONE, &tr );

	if ( tr.fraction < 1.0f )
	{
		surfacedata_t *pdata = physprops->GetSurfaceData( tr.surface.surfaceProps );

		if ( ( pdata->game.material == CHAR_TEX_CONCRETE ) || 
			 ( pdata->game.material == CHAR_TEX_DIRT ) ||
			 ( pdata->game.material == CHAR_TEX_SAND ) )
		{
			UTIL_CreateAntlionDust( tr.endpos + Vector(0,0,24), GetAbsAngles() );
			
			if ( placeDecal )
			{
				UTIL_DecalTrace( &tr, "Antlion.Unburrow" );
			}
		}
	}
}
void CAI_RappelBehavior::SetDescentSpeed()
{
	// Trace to the floor and see how close we're getting. Slow down if we're close.
	// STOP if there's an NPC under us.
	trace_t tr;
	AI_TraceLine( GetOuter()->GetAbsOrigin(), GetOuter()->GetAbsOrigin() - Vector( 0, 0, 8192 ), MASK_SHOT, GetOuter(), COLLISION_GROUP_NONE, &tr );

	float flDist = fabs( GetOuter()->GetAbsOrigin().z - tr.endpos.z );

	float speed = RAPPEL_MAX_SPEED;

	if( flDist <= RAPPEL_DECEL_DIST )
	{
		float factor;
		factor = flDist / RAPPEL_DECEL_DIST;

		speed = MAX( RAPPEL_MIN_SPEED, speed * factor );
	}

	Vector vecNewVelocity = vec3_origin;
	vecNewVelocity.z = -speed;
	GetOuter()->SetAbsVelocity( vecNewVelocity );
}
Пример #19
0
//------------------------------------------------------------------------------
// Purpose : Override base class to check range and visibility
//------------------------------------------------------------------------------
bool CNPC_Launcher::IsValidEnemy( CBaseEntity *pTarget )
{
	// ---------------------------------
	//  Check range
	// ---------------------------------
	float flTargetDist = (GetAbsOrigin() - pTarget->GetAbsOrigin()).Length();
	if (flTargetDist < m_flMinAttackDist)
	{
		return false;
	}
	if (flTargetDist > m_flMaxAttackDist)
	{
		return false;
	}

	if (!FBitSet (m_spawnflags, SF_LAUNCHER_CHECK_LOS))
	{
		return true;
	}
	// ------------------------------------------------------
	// Make sure I can see the target from above my position
	// ------------------------------------------------------
	trace_t tr;

	// Trace from launch position to target position.  
	// Use position above actual barral based on vertical launch speed
	Vector vStartPos = GetAbsOrigin() + Vector(0,0,0.2*m_flLaunchSpeed);
	Vector vEndPos	 = pTarget->GetAbsOrigin();
	AI_TraceLine( vStartPos, vEndPos, MASK_SHOT, pTarget, COLLISION_GROUP_NONE, &tr );

	if (tr.fraction == 1.0)
	{
		return true;
	}
	return false;
}
Пример #20
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CUnitBase::FireBullets( const FireBulletsInfo_t &info )
{
	VPROF_BUDGET( "CUnitBase::FireBullets", VPROF_BUDGETGROUP_UNITS );

	static int	tracerCount;
	trace_t		tr;
	CAmmoDef*	pAmmoDef	= GetAmmoDef();
	int			nDamageType	= pAmmoDef->DamageType(info.m_iAmmoType);
	//int			nAmmoFlags	= pAmmoDef->Flags(info.m_iAmmoType);
	int iNumShots;
	float flActualDamage;

	// the default attacker is ourselves
	CBaseEntity *pAttacker = info.m_pAttacker ? info.m_pAttacker : this;

	ClearMultiDamage();
	g_MultiDamage.SetDamageType( nDamageType | DMG_NEVERGIB );

	Vector vecDir;
	Vector vecEnd;

	// Adjust spread to accuracy
	Vector vecSpread( info.m_vecSpread );
	//vecSpread.x = sin( ( (asin( info.m_vecSpread.x ) * 2.0f) * m_fAccuracy ) / 2.0f );
	//vecSpread.y = sin( ( (asin( info.m_vecSpread.y ) * 2.0f) * m_fAccuracy ) / 2.0f );
	//vecSpread.z = sin( ( (asin( info.m_vecSpread.z ) * 2.0f) * m_fAccuracy ) / 2.0f );

	// Skip multiple entities when tracing
	CWarsBulletsFilter traceFilter( this, COLLISION_GROUP_NONE );
	traceFilter.SetPassEntity( this ); // Standard pass entity for THIS so that it can be easily removed from the list after passing through a portal
	traceFilter.AddEntityToIgnore( info.m_pAdditionalIgnoreEnt );

	CShotManipulator Manipulator( info.m_vecDirShooting );

	iNumShots = info.m_iShots;
	flActualDamage = info.m_flDamage;
	if ( flActualDamage == 0.0 )
	{
		flActualDamage = g_pGameRules->GetAmmoDamage( pAttacker, tr.m_pEnt, info.m_iAmmoType );
	}

	flActualDamage *= m_fAccuracy; // Pretty much a damage modifier

	for (int iShot = 0; iShot < iNumShots; iShot++)
	{
		//vecDir = info.m_vecDirShooting;
		vecDir = Manipulator.ApplySpread( vecSpread );

		vecEnd = info.m_vecSrc + vecDir * info.m_flDistance;

		AI_TraceLine(info.m_vecSrc, vecEnd, MASK_SHOT, &traceFilter, &tr);

		if( unit_debugfirebullets.GetBool() )
		{
#ifdef CLIENT_DLL
			NDebugOverlay::Line(info.m_vecSrc, vecEnd, 255, 0, 0, 255, 0.1f);
			NDebugOverlay::Line(info.m_vecSrc, tr.endpos, 0, 255, 0, 255, 0.1f);
#else
			NDebugOverlay::Line(info.m_vecSrc, vecEnd, 255, 255, 0, 255, 0.1f);
			NDebugOverlay::Line(info.m_vecSrc, tr.endpos, 0, 255, 255, 255, 0.1f);
#endif // CLIENT_DLL
		}

		// Make sure given a valid bullet type
		if (info.m_iAmmoType == -1)
		{
			DevMsg("ERROR: Undefined ammo type!\n");
			return;
		}

		Vector vecTracerDest = tr.endpos;

		// do damage, paint decals
		if (tr.fraction != 1.0)
		{
			CTakeDamageInfo dmgInfo( pAttacker, pAttacker, flActualDamage, nDamageType );
			CalculateBulletDamageForce( &dmgInfo, info.m_iAmmoType, vecDir, tr.endpos );
			dmgInfo.ScaleDamageForce( info.m_flDamageForceScale );
			dmgInfo.SetAmmoType( info.m_iAmmoType );

			(dynamic_cast<CBaseEntity *>(tr.m_pEnt))->DispatchTraceAttack( dmgInfo, vecDir, &tr );

			// Effects only, FireBullets should be called on the client.
			// Dispatching on the server generates far too many events/data!
#ifdef CLIENT_DLL 
			DoImpactEffect( tr, nDamageType );

			Vector vecTracerSrc = vec3_origin;
			ComputeTracerStartPosition( info.m_vecSrc, &vecTracerSrc );

			trace_t Tracer;
			Tracer = tr;
			Tracer.endpos = vecTracerDest;

			MakeTracer( vecTracerSrc, Tracer, pAmmoDef->TracerType(info.m_iAmmoType) );
#endif // CLIENT_DLL
		}
	}

#ifdef GAME_DLL
	ApplyMultiDamage();
#endif // GAME_DLL
}
Пример #21
0
void CNPC_Stalker::StartAttackBeam( void )
{
	if ( m_fBeamEndTime > gpGlobals->curtime || m_fBeamRechargeTime > gpGlobals->curtime )
	{
		// UNDONE: Debug this and fix!?!?!
		m_fBeamRechargeTime = gpGlobals->curtime;
	}
	// ---------------------------------------------
	//  If I don't have a beam yet, create one
	// ---------------------------------------------
	// UNDONE: Why would I ever have a beam already?!?!?!
	if (!m_pBeam)
	{
		Vector vecSrc = LaserStartPosition(GetAbsOrigin());
		trace_t tr;
		AI_TraceLine ( vecSrc, vecSrc + m_vLaserDir * MAX_STALKER_FIRE_RANGE, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr);
		if ( tr.fraction >= 1.0 )
		{
			// too far
			TaskComplete();
			return;
		}

		m_pBeam = CBeam::BeamCreate( "sprites/laser.vmt", 2.0 );
		m_pBeam->PointEntInit( tr.endpos, this );
		m_pBeam->SetEndAttachment( STALKER_LASER_ATTACHMENT );  
		m_pBeam->SetBrightness( 255 );
		m_pBeam->SetNoise( 0 );

		switch (m_eBeamPower)
		{
			case STALKER_BEAM_LOW:
				m_pBeam->SetColor( 255, 0, 0 );
				m_pLightGlow = CSprite::SpriteCreate( "sprites/redglow1.vmt", GetAbsOrigin(), FALSE );
				break;
			case STALKER_BEAM_MED:
				m_pBeam->SetColor( 255, 50, 0 );
				m_pLightGlow = CSprite::SpriteCreate( "sprites/orangeglow1.vmt", GetAbsOrigin(), FALSE );
				break;
			case STALKER_BEAM_HIGH:
				m_pBeam->SetColor( 255, 150, 0 );
				m_pLightGlow = CSprite::SpriteCreate( "sprites/yellowglow1.vmt", GetAbsOrigin(), FALSE );
				break;
		}

		// ----------------------------
		// Light myself in a red glow
		// ----------------------------
		m_pLightGlow->SetTransparency( kRenderGlow, 255, 200, 200, 0, kRenderFxNoDissipation );
		m_pLightGlow->SetAttachment( this, 1 );
		m_pLightGlow->SetBrightness( 255 );
		m_pLightGlow->SetScale( 0.65 );

#if 0
		CBaseEntity *pEnemy = GetEnemy();
		// --------------------------------------------------------
		// Play start up sound - client should always hear this!
		// --------------------------------------------------------
		if (pEnemy != NULL && (pEnemy->IsPlayer()) ) 
		{
			EmitAmbientSound( 0, pEnemy->GetAbsOrigin(), "NPC_Stalker.AmbientLaserStart" );
		}
		else
		{
			EmitAmbientSound( 0, GetAbsOrigin(), "NPC_Stalker.AmbientLaserStart" );
		}
#endif
	}

	SetThink( &CNPC_Stalker::StalkerThink );

	m_flNextNPCThink = GetNextThink();
	SetNextThink( gpGlobals->curtime + g_StalkerBeamThinkTime );
	m_fBeamEndTime = gpGlobals->curtime + STALKER_LASER_DURATION;
}
Пример #22
0
//------------------------------------------------------------------------------
// Purpose : Draw attack beam and do damage / decals
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CNPC_Stalker::DrawAttackBeam(void)
{
	if (!m_pBeam)
		return;

	// ---------------------------------------------
	//	Get beam end point
	// ---------------------------------------------
	Vector vecSrc = LaserStartPosition(GetAbsOrigin());
	trace_t tr;
	AI_TraceLine( vecSrc, vecSrc + m_vLaserDir * MAX_STALKER_FIRE_RANGE, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr);

	CalcBeamPosition();

	bool bInWater = (UTIL_PointContents ( tr.endpos, MASK_WATER ) & MASK_WATER)?true:false;
	// ---------------------------------------------
	//	Update the beam position
	// ---------------------------------------------
	m_pBeam->SetStartPos( tr.endpos );
	m_pBeam->RelinkBeam();

	Vector vAttachPos;
	GetAttachment(STALKER_LASER_ATTACHMENT,vAttachPos);

	Vector vecAimDir = tr.endpos - vAttachPos;
	VectorNormalize( vecAimDir );

	SetAim( vecAimDir );

	// --------------------------------------------
	//  Play burn sounds
	// --------------------------------------------
	CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( tr.m_pEnt );
	if (pBCC)
	{
		if (gpGlobals->curtime > m_fNextDamageTime)
		{
			ClearMultiDamage();

			float damage = 0.0;
			switch (m_eBeamPower)
			{
				case STALKER_BEAM_LOW:
					damage = 1;
					break;
				case STALKER_BEAM_MED:
					damage = 3;
					break;
				case STALKER_BEAM_HIGH:
					damage = 10;
					break;
			}

			CTakeDamageInfo info( this, this, damage, DMG_SHOCK );
			CalculateMeleeDamageForce( &info, m_vLaserDir, tr.endpos );
			pBCC->DispatchTraceAttack( info, m_vLaserDir, &tr );
			ApplyMultiDamage();
			m_fNextDamageTime = gpGlobals->curtime + 0.1;
		}
		if (pBCC->Classify()!=CLASS_BULLSEYE)
		{
			if (!m_bPlayingHitFlesh)
			{
				CPASAttenuationFilter filter( m_pBeam,"NPC_Stalker.BurnFlesh" );
				filter.MakeReliable();

				EmitSound( filter, m_pBeam->entindex(),"NPC_Stalker.BurnFlesh" );
				m_bPlayingHitFlesh = true;
			}
			if (m_bPlayingHitWall)
			{
				StopSound( m_pBeam->entindex(), "NPC_Stalker.BurnWall" );
				m_bPlayingHitWall = false;
			}

			tr.endpos.z -= 24.0f;
			if (!bInWater)
			{
				DoSmokeEffect(tr.endpos + tr.plane.normal * 8);
			}
		}
	}
	
	if (!pBCC || pBCC->Classify()==CLASS_BULLSEYE)
	{
		if (!m_bPlayingHitWall)
		{
			CPASAttenuationFilter filter( m_pBeam, "NPC_Stalker.BurnWall" );
			filter.MakeReliable();

			EmitSound( filter, m_pBeam->entindex(), "NPC_Stalker.BurnWall" );
			m_bPlayingHitWall = true;
		}
		if (m_bPlayingHitFlesh)
		{
			StopSound(m_pBeam->entindex(), "NPC_Stalker.BurnFlesh" );
			m_bPlayingHitFlesh = false;
		}

		UTIL_DecalTrace( &tr, "RedGlowFade");
		UTIL_DecalTrace( &tr, "FadingScorch" );
		
		tr.endpos.z -= 24.0f;
		if (!bInWater)
		{
			DoSmokeEffect(tr.endpos + tr.plane.normal * 8);
		}
	}

	if (bInWater)
	{
		UTIL_Bubbles(tr.endpos-Vector(3,3,3),tr.endpos+Vector(3,3,3),10);
	}

	/*
	CBroadcastRecipientFilter filter;
	TE_DynamicLight( filter, 0.0, EyePosition(), 255, 0, 0, 5, 0.2, 0 );
	*/
}
Пример #23
0
//-----------------------------------------------------------------------------
// Purpose: Return true if pTestHint passes the criteria specified in hintCriteria
//-----------------------------------------------------------------------------
bool CAI_Hint::HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria, const Vector &position, float *flNearestDistance, bool bIgnoreLock, bool bIgnoreHintType )
{
	// Cannot be locked
	if ( !bIgnoreLock && IsLocked() )
	{
		REPORTFAILURE( "Node is locked." );
		return false;
	}

	if ( !bIgnoreHintType && !hintCriteria.MatchesHintType( HintType() ) )
	{
		return false;
	}

	if ( GetMinState() > NPC_STATE_IDLE || GetMaxState() < NPC_STATE_COMBAT )
	{
		if ( pNPC && ( pNPC->GetState() < GetMinState() || pNPC->GetState() > GetMaxState() ) )
		{
			REPORTFAILURE( "NPC not in correct state." );
			return false;
		}
	}

	// See if we're filtering by group name
	if ( hintCriteria.GetGroup() != NULL_STRING )
	{
		AssertIsValidString( GetGroup() );
		AssertIsValidString( hintCriteria.GetGroup() );
		if ( GetGroup() == NULL_STRING || GetGroup() != hintCriteria.GetGroup() )
		{
			Assert(GetGroup() == NULL_STRING || strcmp( STRING(GetGroup()), STRING(hintCriteria.GetGroup())) != 0 );
			REPORTFAILURE( "Doesn't match NPC hint group." );
			return false;
		}
	}

	// If we're watching for include zones, test it
	if ( ( hintCriteria.HasIncludeZones() ) && ( hintCriteria.InIncludedZone( GetAbsOrigin() ) == false ) )
	{
		REPORTFAILURE( "Not inside include zones." );
		return false;
	}

	// If we're watching for exclude zones, test it
	if ( ( hintCriteria.HasExcludeZones() ) && ( hintCriteria.InExcludedZone( GetAbsOrigin() ) ) )
	{
		REPORTFAILURE( "Inside exclude zones." );
		return false;
	}

	// See if the class handles this hint type
	if ( ( pNPC != NULL ) && ( pNPC->FValidateHintType( this ) == false ) )
	{
		REPORTFAILURE( "NPC doesn't know how to handle that type." );
		return false;
	}

	if ( hintCriteria.HasFlag(bits_HINT_NPC_IN_NODE_FOV) )
	{
		if ( pNPC == NULL )
		{
			AssertMsg(0,"Hint node attempted to verify NPC in node FOV without NPC!\n");
		}
		else
		{
			if( !IsInNodeFOV(pNPC) )
			{
				REPORTFAILURE( "NPC Not in hint's FOV" );
				return false;
			}
		}
	}

	if ( hintCriteria.HasFlag( bits_HINT_NODE_IN_AIMCONE ) )
	{
		if ( pNPC == NULL )
		{
			AssertMsg( 0, "Hint node attempted to find node in aimcone without specifying NPC!\n" );
		}
		else
		{
			if( !pNPC->FInAimCone( GetAbsOrigin() ) )
			{
				REPORTFAILURE( "Hint isn't in NPC's aimcone" );
				return false;
			}
		}
	}

	if ( hintCriteria.HasFlag( bits_HINT_NODE_IN_VIEWCONE ) )
	{
		if ( pNPC == NULL )
		{
			AssertMsg( 0, "Hint node attempted to find node in viewcone without specifying NPC!\n" );
		}
		else
		{
			if( !pNPC->FInViewCone( this ) )
			{
				REPORTFAILURE( "Hint isn't in NPC's viewcone" );
				return false;
			}
		}
	}

	{
		AI_PROFILE_SCOPE( HINT_FVisible );
		// See if we're requesting a visible node
		if ( hintCriteria.HasFlag( bits_HINT_NODE_VISIBLE ) )
		{
			if ( pNPC == NULL )
			{
				//NOTENOTE: If you're hitting this, you've asked for a visible node without specifing an NPC!
				AssertMsg( 0, "Hint node attempted to find visible node without specifying NPC!\n" );
			}
			else
			{
				if( m_NodeData.nNodeID == NO_NODE )
				{
					// This is just an info_hint, not a node.
					if( !pNPC->FVisible( this ) )
					{
						REPORTFAILURE( "Hint isn't visible to NPC." );
						return false;
					}
				}
				else
				{
					// This hint associated with a node.
					trace_t tr;
					Vector vHintPos;
					GetPosition(pNPC,&vHintPos);
					AI_TraceLine ( pNPC->EyePosition(), vHintPos + pNPC->GetViewOffset(), MASK_NPCSOLID_BRUSHONLY, pNPC, COLLISION_GROUP_NONE, &tr );
					if ( tr.fraction != 1.0f )
					{
						REPORTFAILURE( "Node isn't visible to NPC." );
						return false;
					}
				}
			}
		}
	}

	// Check for clear if requested
	if ( hintCriteria.HasFlag( bits_HINT_NODE_CLEAR ) )
	{
		if ( pNPC == NULL )
		{
			//NOTENOTE: If you're hitting this, you've asked for a clear node without specifing an NPC!
			AssertMsg( 0, "Hint node attempted to find clear node without specifying NPC!\n" );
		}
		else
		{
			trace_t tr;
			// Can my bounding box fit there?
			AI_TraceHull ( GetAbsOrigin(), GetAbsOrigin(), pNPC->WorldAlignMins(), pNPC->WorldAlignMaxs(), 
				MASK_SOLID, pNPC, COLLISION_GROUP_NONE, &tr );

			if ( tr.fraction != 1.0 )
			{
				REPORTFAILURE( "Node isn't clear." );
				return false;
			}
		}
	}

	// See if this is our next, closest node
	if ( hintCriteria.HasFlag( bits_HINT_NODE_NEAREST ) )
	{
		Assert( flNearestDistance );

		// Calculate our distance
		float distance = (GetAbsOrigin() - position).Length();

		// Must be closer than the current best
		if ( distance > *flNearestDistance )
		{
			REPORTFAILURE( "Not the nearest node." );
			return false;
		}

		// Remember the distance
		*flNearestDistance = distance;
	}

	// Must either be visible or not if requested
	if ( hintCriteria.HasFlag( bits_HINT_NODE_NOT_VISIBLE_TO_PLAYER|bits_HINT_NODE_VISIBLE_TO_PLAYER ) )
	{
		bool bWasSeen = false;
		// Test all potential seers
		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
				Vector vLookDir = pPlayer->EyeDirection3D();
				Vector vTargetDir = GetAbsOrigin() - pPlayer->EyePosition();
				VectorNormalize(vTargetDir);

				float fDotPr = DotProduct(vLookDir,vTargetDir);
				if ( fDotPr > 0 )
				{
					trace_t tr;
					UTIL_TraceLine( pPlayer->EyePosition(), GetAbsOrigin(), MASK_SOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr);
					
					if ( tr.fraction == 1.0 )
					{
						if ( hintCriteria.HasFlag( bits_HINT_NODE_NOT_VISIBLE_TO_PLAYER ) )
						{
							REPORTFAILURE( "Node is visible to player." );
							return false;
						}
						bWasSeen = true;
					}
				}
			}
		}

		if ( !bWasSeen && hintCriteria.HasFlag( bits_HINT_NODE_VISIBLE_TO_PLAYER ) )
		{
			REPORTFAILURE( "Node isn't visible to player." );
			return false;
		}
	}

	return true;
}
void CASW_Queen_Divers::ASWTraceBleed( float flDamage, const Vector &vecDir, trace_t *ptr, int bitsDamageType )
{
	if ((BloodColor() == DONT_BLEED) || (BloodColor() == BLOOD_COLOR_MECH))
	{
		return;
	}

	if (flDamage == 0)
		return;

	if (! (bitsDamageType & (DMG_CRUSH | DMG_BULLET | DMG_SLASH | DMG_BLAST | DMG_CLUB | DMG_AIRBOAT)))
		return;

	// make blood decal on the wall!
	trace_t Bloodtr;
	Vector vecTraceDir;
	float flNoise;
	int cCount;
	int i;

#ifdef GAME_DLL
	if ( !IsAlive() )
	{
		// dealing with a dead npc.
		if ( GetMaxHealth() <= 0 )
		{
			// no blood decal for a npc that has already decalled its limit.
			return;
		}
		else
		{
			m_iMaxHealth -= 1;
		}
	}
#endif

	if (flDamage < 10)
	{
		flNoise = 0.1;
		cCount = 1;
	}
	else if (flDamage < 25)
	{
		flNoise = 0.2;
		cCount = 2;
	}
	else
	{
		flNoise = 0.3;
		cCount = 4;
	}

	float flTraceDist = (bitsDamageType & DMG_AIRBOAT) ? 384 : 172;
	for ( i = 0 ; i < cCount ; i++ )
	{
		vecTraceDir = vecDir * -1;// trace in the opposite direction the shot came from (the direction the shot is going)

		vecTraceDir.x += random->RandomFloat( -flNoise, flNoise );
		vecTraceDir.y += random->RandomFloat( -flNoise, flNoise );
		vecTraceDir.z += random->RandomFloat( -flNoise, flNoise );

		// Don't bleed on grates.
		Vector vecEndPos = ptr->endpos;
		AI_TraceLine( vecEndPos, vecEndPos + vecTraceDir * -flTraceDist, MASK_SOLID_BRUSHONLY & ~CONTENTS_GRATE, this, COLLISION_GROUP_NONE, &Bloodtr);

		if ( Bloodtr.fraction != 1.0 )
		{
			UTIL_BloodDecalTrace( &Bloodtr, BloodColor() );
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
bool CDarknessLightSourcesSystem::IsEntityVisibleToTarget( CBaseEntity *pLooker, CBaseEntity *pTarget )
{
	if ( pTarget->IsEffectActive( EF_BRIGHTLIGHT ) || pTarget->IsEffectActive( EF_DIMLIGHT ) )
		return true;

	bool bDebug = g_debug_darkness.GetBool();
	if ( bDebug && pLooker )
	{
		bDebug = (pLooker->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) != 0;
	}

	trace_t tr;

	// Loop through all the light sources. Do it backwards, so we can remove dead ones.
	for ( int i = m_LightSources.Count() - 1; i >= 0; i-- )
	{
		// Removed?
		if ( m_LightSources[i].hEntity == NULL || m_LightSources[i].hEntity->IsMarkedForDeletion() )
		{
			m_LightSources.FastRemove( i );
			continue;
		}

		CInfoDarknessLightSource *pLightSource = m_LightSources[i].hEntity;

		// Close enough to a light source?
		float flDistanceSqr = (pTarget->WorldSpaceCenter() - pLightSource->GetAbsOrigin()).LengthSqr();
		if ( flDistanceSqr < m_LightSources[i].flLightRadiusSqr )
		{
			if ( pLightSource->ShouldIgnoreLOS() )
			{
				if ( bDebug )
				{
					NDebugOverlay::Line( pTarget->WorldSpaceCenter(), pLightSource->GetAbsOrigin(), 0,255,0,true, 0.1);
				}
				return true;
			}

			// Check LOS from the light to the target
			CTraceFilterSkipTwoEntities filter( pTarget, pLooker, COLLISION_GROUP_NONE );
			AI_TraceLine( pTarget->WorldSpaceCenter(), pLightSource->GetAbsOrigin(), MASK_OPAQUE, &filter, &tr );
			if ( tr.fraction == 1.0 )
			{
				if ( bDebug )
				{
					NDebugOverlay::Line( tr.startpos, tr.endpos, 0,255,0,true, 0.1);
				}
				return true;
			}

			if ( bDebug )
			{
				NDebugOverlay::Line( tr.startpos, tr.endpos, 255,0,0,true, 0.1);
				NDebugOverlay::Line( tr.endpos, pLightSource->GetAbsOrigin(), 128,0,0,true, 0.1);
			}

			// If the target is within the radius of the light, don't do sillhouette checks
			continue;
		}

 		if ( !pLooker )
			continue;

		// Between a light source and the looker?
		Vector vecLookerToLight = (pLightSource->GetAbsOrigin() - pLooker->WorldSpaceCenter());
		Vector vecLookerToTarget = (pTarget->WorldSpaceCenter() - pLooker->WorldSpaceCenter());
		float flDistToSource = VectorNormalize( vecLookerToLight );
		float flDistToTarget = VectorNormalize( vecLookerToTarget );
 		float flDot = DotProduct( vecLookerToLight, vecLookerToTarget );
		if ( flDot > 0 )
		{
			// Make sure the target is in front of the lightsource
			if ( flDistToTarget < flDistToSource )
			{
				if ( bDebug )
				{
					NDebugOverlay::Line( pLooker->WorldSpaceCenter(), pLooker->WorldSpaceCenter() + (vecLookerToLight * 128), 255,255,255,true, 0.1);
					NDebugOverlay::Line( pLooker->WorldSpaceCenter(), pLooker->WorldSpaceCenter() + (vecLookerToTarget * 128), 255,0,0,true, 0.1);
				}

				// Now, we need to find out if the light source is obscured by anything. 
				// To do this, we want to calculate the point of intersection between the light source 
				// sphere and the line from the looker through the target. 
 				float flASqr = (flDistToSource * flDistToSource);
				float flB = -2 * flDistToSource * flDot;
				float flCSqr = m_LightSources[i].flLightRadiusSqr;
				float flDesc = (flB * flB) - (4 * (flASqr - flCSqr));
				if ( flDesc >= 0 )
				{
 					float flLength = (-flB - sqrt(flDesc)) / 2;
  					Vector vecSpherePoint = pLooker->WorldSpaceCenter() + (vecLookerToTarget * flLength);

					// We've got the point of intersection. See if we can see it.
					CTraceFilterSkipTwoEntities filter( pTarget, pLooker, COLLISION_GROUP_NONE );
					AI_TraceLine( pLooker->EyePosition(), vecSpherePoint, MASK_SOLID_BRUSHONLY, &filter, &tr );

					if ( bDebug )
					{
						if (tr.fraction != 1.0)
						{
							NDebugOverlay::Line( pLooker->WorldSpaceCenter(), vecSpherePoint, 255,0,0,true, 0.1);
						}
						else
						{
							NDebugOverlay::Line( pLooker->WorldSpaceCenter(), vecSpherePoint, 0,255,0,true, 0.1);
							NDebugOverlay::Line( pLightSource->GetAbsOrigin(), vecSpherePoint, 255,0,0,true, 0.1);
						}
					}

					if ( tr.fraction == 1.0 )
						return true;
				}
			}
		}
	}

	return false;
}
Пример #26
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : pTask - 
//-----------------------------------------------------------------------------
void CNPC_Crow::RunTask( const Task_t *pTask )
{
	switch ( pTask->iTask )
	{
		case TASK_CROW_TAKEOFF:
		{
			if ( GetNavigator()->IsGoalActive() )
			{
				GetMotor()->SetIdealYawToTargetAndUpdate( GetAbsOrigin() + GetNavigator()->GetCurWaypointPos(), AI_KEEP_YAW_SPEED );
			}
			else
				TaskFail( FAIL_NO_ROUTE );

			if ( IsActivityFinished() )
			{
				TaskComplete();
				SetIdealActivity( ACT_FLY );

				m_bSoar = false;
				m_flSoarTime = gpGlobals->curtime + random->RandomFloat( 2, 5 );
			}
			
			break;
		}

		case TASK_CROW_HOP:
		{
			if ( IsActivityFinished() )
			{
				TaskComplete();
				SetIdealActivity( ACT_IDLE );
			}

			if ( ( GetAbsOrigin().z < m_flHopStartZ ) && ( !( GetFlags() & FL_ONGROUND ) ) )
			{
				//
				// We've hopped off of something! See if we're going to fall very far.
				//
				trace_t tr;
				AI_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, -32 ), MASK_SOLID, this, HL2COLLISION_GROUP_CROW, &tr );
				if ( tr.fraction == 1.0f )
				{
					//
					// We're falling! Better fly away. SelectSchedule will check ONGROUND and do the right thing.
					//
					TaskComplete();
				}
				else
				{
					//
					// We'll be okay. Don't check again unless what we're hopping onto moves
					// out from under us.
					//
					m_flHopStartZ = GetAbsOrigin().z - ( 32 * tr.fraction );
				}
			}

			break;
		}

		//
		// Face the direction we are flying.
		//
		case TASK_CROW_FLY:
		{
			GetMotor()->SetIdealYawToTargetAndUpdate( GetAbsOrigin() + GetAbsVelocity(), AI_KEEP_YAW_SPEED );

			break;
		}

		case TASK_CROW_FALL_TO_GROUND:
		{
			if ( GetFlags() & FL_ONGROUND )
			{
				SetFlyingState( FlyState_Walking );
				TaskComplete();
			}
			break;
		}

		case TASK_CROW_WAIT_FOR_BARNACLE_KILL:
		{
			if ( m_flNextFlinchTime < gpGlobals->curtime )
			{
				m_flNextFlinchTime = gpGlobals->curtime + random->RandomFloat( 0.5f, 2.0f );
				// dvs: TODO: squirm
				// dvs: TODO: spawn feathers
				EmitSound( "NPC_Crow.Squawk" );
			}
			break;
		}

		default:
		{
			CAI_BaseNPC::RunTask( pTask );
		}
	}
}
Пример #27
0
void CNPC_Roller::Unstick( void )
{
	CBaseEntity		*pList[ 16 ];
	IPhysicsObject	*pPhysObj;
	int				i;
	Vector			vecDirToEnemy;
	Vector			vecDirToObject;

	m_flWaitFinished = gpGlobals->curtime;

	int count = UTIL_EntitiesInBox( pList, 16, GetAbsOrigin() - vecDelta, GetAbsOrigin() + vecDelta, 0 );

	m_vecUnstickDirection = vec3_origin;

	for( i = 0 ; i < count ; i++ )
	{
		pPhysObj = pList[ i ]->VPhysicsGetObject();

		if( !pPhysObj || pList[ i ]->m_iClassname == m_iClassname )
		{
			// Only consider physics objects. Exclude rollers.
			continue;
		}

		if( pPhysObj->GetMass() <= ROLLER_MAX_PUSH_MASS )
		{
			// Try to bash this physics object.
			trace_t tr;

			AI_TraceLine( GetAbsOrigin(), pList[ i ]->GetAbsOrigin(), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); 

			if( tr.fraction == 1.0 || tr.m_pEnt == pList[ i ] )
			{
				// Roll towards this item if the trace hits nothing, or
				// the trace hits the object.
				Vector vecBashDir;

				vecBashDir = pList[ i ]->GetAbsOrigin() - GetAbsOrigin();
				VectorNormalize( vecBashDir );
				vecBashDir.z = 0.0;

				//NDebugOverlay::Line( GetAbsOrigin(), pList[ i ]->GetAbsOrigin(), 0,255,0, true, 2 );

				m_vecUnstickDirection = vecBashDir * 80;

				return;
			}
		}
	}

	// No physics objects. Just pick a direction with some clearance and go there.

#define ROLLER_UNSTICK_DIST 80
	Vector vecDirections[ 4 ] = 
	{
		Vector(  0,	ROLLER_UNSTICK_DIST, 0 ),
		Vector(  ROLLER_UNSTICK_DIST,	0, 0 ),
		Vector(  0, -ROLLER_UNSTICK_DIST, 0 ),
		Vector( -ROLLER_UNSTICK_DIST,  0, 0 )
	};

	trace_t tr;

	for( i = 0 ; i < 4 ; i++ )
	{
		AI_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vecDirections[ i ], MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); 

		if( tr.fraction == 1.0 )
		{
			m_vecUnstickDirection = vecDirections[ i ];

			//NDebugOverlay::Line( GetLocalOrigin(), GetLocalOrigin() + m_vecUnstickDirection, 255,255,0, true, 2 );

			// Roll in this direction for a couple of seconds.
			Msg( "unsticking!\n" );
			return;
		}
	}
}
//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CNPC_MissileDefense::FireCannons( void )
{
	// ----------------------------------------------
	//  Make sure I have an enemy
	// ----------------------------------------------
	if (GetEnemy() == NULL)
	{
		return;
	}

	// ----------------------------------------------
	//  Make sure I have ammo
	// ----------------------------------------------
	if( m_iAmmoLoaded < 1 )
	{
		return;
	}
	// ----------------------------------------------
	// Make sure gun it pointing in right direction	
	// ----------------------------------------------
	Vector vGunDir;
	GetGunAim( &vGunDir );
	Vector vTargetPos;
	EnemyShootPosition(GetEnemy(),&vTargetPos);

	Vector vTargetDir = vTargetPos - GetAbsOrigin();
	VectorNormalize( vTargetDir );

	float fDotPr = DotProduct( vGunDir, vTargetDir );
	if (fDotPr < 0.95)
	{
		return;
	}

	// ----------------------------------------------
	// Check line of sight
	// ----------------------------------------------
	trace_t tr;
	AI_TraceLine( GetEnemy()->EyePosition(), GetAbsOrigin(), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr);
	if (tr.fraction < 1.0)
	{
		return;
	}

	Vector vecRight;
	Vector vecDir;
	Vector vecCenter;
	AngleVectors( GetLocalAngles(), NULL, &vecRight, NULL );

	vecCenter = WorldSpaceCenter();

	if( GetEnemy() == NULL )
	{
		return;
	}

	bool fSound = false;
	if( random->RandomInt( 0, 3 ) == 0 )
	{
		fSound = true;
	}


	EmitSound( "NPC_MissileDefense.Attack" );

	Vector vecGun;
	QAngle vecAng;
	
	GetAttachment( MD_AP_LGUN, vecGun, vecAng );

	Vector vecTarget;
	EnemyShootPosition(GetEnemy(),&vecTarget);

	vecDir = vecTarget - vecCenter;
	VectorNormalize(vecDir);
	vecDir.x += random->RandomFloat( -NOISE, NOISE );
	vecDir.y += random->RandomFloat( -NOISE, NOISE );

	Vector vecStart = vecGun + vecDir * 110;
	Vector vecEnd	= vecGun + vecDir * 4096;
	UTIL_Tracer( vecStart, vecEnd, 0, TRACER_DONT_USE_ATTACHMENT, 3000 + random->RandomFloat( 0, 2000 ), fSound );

	vecDir = vecTarget - vecCenter;
	VectorNormalize(vecDir);
	vecDir.x += random->RandomFloat( -NOISE, NOISE );
	vecDir.y += random->RandomFloat( -NOISE, NOISE );
	vecDir.z += random->RandomFloat( -NOISE, NOISE );

	GetAttachment( MD_AP_RGUN, vecGun, vecAng );
	vecStart = vecGun + vecDir * 110;
	vecEnd = vecGun + vecDir * 4096;
	UTIL_Tracer( vecStart, vecEnd, 0, TRACER_DONT_USE_ATTACHMENT, 3000 + random->RandomFloat( 0, 2000 ) );

	m_iAmmoLoaded -= 2;

	if( m_iAmmoLoaded < 1 )
	{
		// Incite a reload.
		EmitSound( "NPC_MissileDefense.Reload" );
		m_flReloadedTime = gpGlobals->curtime + 0.3;
		return;
	}

	// Do damage to the missile based on distance.
	// if < 1, make damage 0.

	float flDist = (GetEnemy()->GetLocalOrigin() - vecGun).Length();
	float flDamage;

	flDamage = 4000 - flDist;

	flDamage /= 1000.0;

	if( flDamage > 0 )
	{
		if( flDist <= 1500 )
		{
			flDamage *= 2;
		}

		CTakeDamageInfo info( this, this, flDamage, DMG_MISSILEDEFENSE );
		CalculateBulletDamageForce( &info, GetAmmoDef()->Index("SMG1"), vecDir, GetEnemy()->GetAbsOrigin() );
		GetEnemy()->TakeDamage( info );
	}
}
Пример #29
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : &Steer - 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CNPC_Ichthyosaur::SteerAvoidObstacles(Vector &Steer, const Vector &Velocity, const Vector &Forward, const Vector &Right, const Vector &Up)
{
	trace_t	tr;

	bool	collided = false;
	Vector	dir = Velocity;
	float	speed = VectorNormalize( dir );

	//Look ahead one second and avoid whatever is in our way.
	AI_TraceHull( GetAbsOrigin(), GetAbsOrigin() + (dir*speed), GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr );

	Vector	forward;

	GetVectors( &forward, NULL, NULL );

	//If we're hitting our enemy, just continue on
	if ( ( GetEnemy() != NULL ) && ( tr.m_pEnt == GetEnemy() ) )
		return false;

	if ( tr.fraction < 1.0f )
	{
		CBaseEntity *pBlocker = tr.m_pEnt;
		
		if ( ( pBlocker != NULL ) && ( pBlocker->MyNPCPointer() != NULL ) )
		{
			DevMsg( 2, "Avoiding an NPC\n" );

			Vector HitOffset = tr.endpos - GetAbsOrigin();

			Vector SteerUp = CrossProduct( HitOffset, Velocity );
			Steer = CrossProduct(  SteerUp, Velocity  );
			VectorNormalize( Steer );

			/*Vector probeDir = tr.endpos - GetAbsOrigin();
			Vector normalToProbeAndWallNormal = probeDir.Cross( tr.plane.normal );
			
			Steer = normalToProbeAndWallNormal.Cross( probeDir );
			VectorNormalize( Steer );*/

			if ( tr.fraction > 0 )
			{
				Steer = (Steer * Velocity.Length()) / tr.fraction;
				//NDebugOverlay::Line( GetLocalOrigin(), GetLocalOrigin()+Steer, 255, 0, 0, false, 0.1f );
			}
			else
			{
				Steer = (Steer * 1000 * Velocity.Length());
				//NDebugOverlay::Line( GetLocalOrigin(), GetLocalOrigin()+Steer, 255, 0, 0, false, 0.1f );
			}
		}
		else
		{
			if ( ( pBlocker != NULL ) && ( pBlocker == GetEnemy() ) )
			{
				DevMsg( "Avoided collision\n" );
				return false;
			}

			DevMsg( 2, "Avoiding the world\n" );
			
			Vector	steeringVector = tr.plane.normal;

			if ( tr.fraction == 0.0f )
				return false;

			Steer = steeringVector * ( Velocity.Length() / tr.fraction );
			
			//NDebugOverlay::Line( GetLocalOrigin(), GetLocalOrigin()+Steer, 255, 0, 0, false, 0.1f );
		}

		//return true;
		collided = true;
	}

	//Try to remain 8 feet above the ground.
	AI_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector(0, 0, -ICH_HEIGHT_PREFERENCE), MASK_NPCSOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );

	if ( tr.fraction < 1.0f )
	{
		Steer += Vector( 0, 0, m_vecAccelerationMax.z / tr.fraction );
		collided = true;
	}
	
	//Stay under the surface
	if ( m_bIgnoreSurface == false )
	{
		float waterLevel = ( UTIL_WaterLevel( GetAbsOrigin(), GetAbsOrigin().z, GetAbsOrigin().z+ICH_DEPTH_PREFERENCE ) - GetAbsOrigin().z ) / ICH_DEPTH_PREFERENCE;

		if ( waterLevel < 1.0f )
		{
			Steer += -Vector( 0, 0, m_vecAccelerationMax.z / waterLevel );
			collided = true;
		}
	}

	return collided;
}
void CNPC_Portal_GroundTurret::Shoot()
{
	FireBulletsInfo_t info;

	Vector vecSrc = EyePosition();
	Vector vecDir;

	GetVectors( &vecDir, NULL, NULL );

	for( int i = 0 ; i < 1 ; i++ )
	{
		info.m_vecSrc = vecSrc;

		if( i > 0 || !GetEnemy()->IsPlayer() )
		{
			// Subsequent shots or shots at non-players random
			GetVectors( &info.m_vecDirShooting, NULL, NULL );
			info.m_vecSpread = m_vecSpread;
		}
		else
		{
			// First shot is at the enemy.
			info.m_vecDirShooting = GetActualShootTrajectory( vecSrc );
			info.m_vecSpread = VECTOR_CONE_PRECALCULATED;
		}

		info.m_iTracerFreq = 1;
		info.m_iShots = 1;
		info.m_pAttacker = this;
		info.m_flDistance = MAX_COORD_RANGE;
		info.m_iAmmoType = m_iAmmoType;

		FireBullets( info );

		trace_t tr;
		CTraceFilterSkipTwoEntities traceFilter( this, info.m_pAdditionalIgnoreEnt, COLLISION_GROUP_NONE );
		Vector vecEnd = info.m_vecSrc + vecDir * info.m_flDistance;
		AI_TraceLine( info.m_vecSrc, vecEnd, MASK_SHOT, &traceFilter, &tr );

		if ( tr.m_pEnt && !tr.m_pEnt->IsPlayer() && ( vecDir * info.m_flDistance * tr.fraction ).Length() < 16.0f )
		{
			CTakeDamageInfo damageInfo;
			damageInfo.SetAttacker( this );
			damageInfo.SetDamageType( DMG_BULLET );
			damageInfo.SetDamage( 20.0f );

			TakeDamage( damageInfo );

			EmitSound( "NPC_FloorTurret.DryFire" );
		}
	}

	// Do the AR2 muzzle flash
	CEffectData data;
	data.m_nEntIndex = entindex();
	data.m_nAttachmentIndex = LookupAttachment( "eyes" );
	data.m_flScale = 1.0f;
	data.m_fFlags = MUZZLEFLASH_COMBINE;
	DispatchEffect( "MuzzleFlash", data );

	EmitSound( "NPC_FloorTurret.ShotSounds" );

	m_flTimeNextShoot = gpGlobals->curtime + 0.09;
}