//-----------------------------------------------------------------------------
// Purpose: 
// Input  : &traceHit - 
//-----------------------------------------------------------------------------
bool CBaseHL2MPBludgeonWeapon::ImpactWater( const Vector &start, const Vector &end )
{
	//FIXME: This doesn't handle the case of trying to splash while being underwater, but that's not going to look good
	//		 right now anyway...
	
	// We must start outside the water
	if ( UTIL_PointContents( start ) & (CONTENTS_WATER|CONTENTS_SLIME))
		return false;

	// We must end inside of water
	if ( !(UTIL_PointContents( end ) & (CONTENTS_WATER|CONTENTS_SLIME)))
		return false;

	trace_t	waterTrace;

	UTIL_TraceLine( start, end, (CONTENTS_WATER|CONTENTS_SLIME), GetOwner(), COLLISION_GROUP_NONE, &waterTrace );

	if ( waterTrace.fraction < 1.0f )
	{
#ifndef CLIENT_DLL
		CEffectData	data;

		data.m_fFlags  = 0;
		data.m_vOrigin = waterTrace.endpos;
		data.m_vNormal = waterTrace.plane.normal;
		data.m_flScale = 8.0f;

		// See if we hit slime
		if ( waterTrace.contents & CONTENTS_SLIME )
		{
			data.m_fFlags |= FX_WATER_IN_SLIME;
		}

		DispatchEffect( "watersplash", data );			
#endif
	}

	return true;
}
Пример #2
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CObjectSentrygun::OnGoActive( void )
{
	/*
	CTFPlayer *pBuilder = GetBuilder();

	Assert( pBuilder );

	if ( !pBuilder )
		return;
	*/
	SetModel( SENTRY_MODEL_LEVEL_1 );

	m_iState.Set( SENTRY_STATE_SEARCHING );

	// Orient it
	QAngle angles = GetAbsAngles();

	m_vecCurAngles.y = UTIL_AngleMod( angles.y );
	m_iRightBound = UTIL_AngleMod( (int)angles.y - 50 );
	m_iLeftBound = UTIL_AngleMod( (int)angles.y + 50 );
	if ( m_iRightBound > m_iLeftBound )
	{
		m_iRightBound = m_iLeftBound;
		m_iLeftBound = UTIL_AngleMod( (int)angles.y - 50);
	}

	// Start it rotating
	m_vecGoalAngles.y = m_iRightBound;
	m_vecGoalAngles.x = m_vecCurAngles.x = 0;
	m_bTurningRight = true;

	EmitSound( "Building_Sentrygun.Built" );

	// if our eye pos is underwater, we're waterlevel 3, else 0
	bool bUnderwater = ( UTIL_PointContents( EyePosition() ) & MASK_WATER ) ? true : false;
	SetWaterLevel( ( bUnderwater ) ? 3 : 0 );	

	m_iAmmoShells = m_iMaxAmmoShells;

	// Init attachments for level 1 sentry gun
	m_iAttachments[SENTRYGUN_ATTACHMENT_MUZZLE] = LookupAttachment( "muzzle" );
	m_iAttachments[SENTRYGUN_ATTACHMENT_MUZZLE_ALT] = 0;
	m_iAttachments[SENTRYGUN_ATTACHMENT_ROCKET_L] = 0;
	m_iAttachments[SENTRYGUN_ATTACHMENT_ROCKET_R] = 0;

	BaseClass::OnGoActive();

}
Пример #3
0
void CGrenade::Explode(TraceResult *pTrace, int bitsDamageType)
{
	pev->model = 0;
	pev->solid = SOLID_NOT;
	pev->takedamage = DAMAGE_NO;

	if (pTrace->flFraction != 1)
		pev->origin = pTrace->vecEndPos + (pTrace->vecPlaneNormal * (pev->dmg - 24) * 0.6);

	int iContents = UTIL_PointContents(pev->origin);
	CSoundEnt::InsertSound(bits_SOUND_COMBAT, pev->origin, NORMAL_EXPLOSION_VOLUME, 3);
	entvars_t *pevOwner;

	if (pev->owner)
		pevOwner = VARS(pev->owner);
	else
		pevOwner = NULL;

	pev->owner = NULL;
	RadiusFlash(pev->origin, pev, pevOwner, 4);

	if (RANDOM_FLOAT(0, 1) < 0.5)
		UTIL_DecalTrace(pTrace, DECAL_SCORCH1);
	else
		UTIL_DecalTrace(pTrace, DECAL_SCORCH2);

	float flRndSound = RANDOM_FLOAT(0, 1);

	switch (RANDOM_LONG(0, 1))
	{
		case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/flashbang-1.wav", 0.55, ATTN_NORM); break;
		case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/flashbang-2.wav", 0.55, ATTN_NORM); break;
	}

	pev->effects |= EF_NODRAW;
	SetThink(&CGrenade::Smoke);
	pev->velocity = g_vecZero;
	pev->nextthink = gpGlobals->time + 0.3;

	if (iContents != CONTENTS_WATER)
	{
		int sparkCount = RANDOM_LONG(0, 3);

		for (int i = 0; i < sparkCount; i++)
			Create("spark_shower", pev->origin, pTrace->vecPlaneNormal, NULL);
	}
}
Пример #4
0
void CGrenade::SG_Smoke( void )
{
    if( UTIL_PointContents( pev->origin ) == CONTENTS_WATER )
    {
        UTIL_Bubbles( pev->origin - Vector( 64, 64, 64 ), pev->origin + Vector( 64, 64, 64 ), 100 );
    }
    else
    {
        UTIL_MakeVectors( pev->angles );

        Vector randomDir = gpGlobals->v_forward * RANDOM_FLOAT( 3, 8 );

        m_fLightSmoke = (int)(( ( m_fLightSmoke * 180 / M_PI ) + 30 )) % 360;

        // TODO: Check me.
        PLAYBACK_EVENT_FULL( 0,
                             NULL,
                             m_usEvent,
                             0.0,
                             pev->origin,
                             m_SGExplosionPos,
                             randomDir.x * cos( 180 / M_PI ) - randomDir.y * cos( 180 / M_PI ),
                             randomDir.x * sin( 180 / M_PI ) + randomDir.y * sin( 180 / M_PI ),
                             cos( 180 / M_PI ) * 100.0,
                             4,
                             m_bSGMulti,
                             6 );
    }

    if( m_SGSmoke <= 20 )
    {
        pev->nextthink = gpGlobals->time + 1.0;
        SetThink( &CGrenade::SG_Smoke );

        ++m_SGSmoke;
    }
    else
    {
        pev->effects |= EF_NODRAW;

        // TODO: Implements this.
        //TheBots->RemoveGrenade( this );

        UTIL_Remove( this );
    }
}
Пример #5
0
void CGrenade::SG_Smoke(void)
{
	if (UTIL_PointContents(pev->origin) != CONTENTS_WATER)
	{
		Vector  vecDir;
		float   interval[2];
		int     maxSmokePuffs;

		UTIL_MakeVectors(pev->angles);

		vecDir = gpGlobals->v_forward * RANDOM_FLOAT(3, 8);

		maxSmokePuffs = (int)(RANDOM_FLOAT(1.5, 3.5) * 100);

		interval[0] = vecDir.x * cos((float)m_angle * (180 / M_PI)) - vecDir.y * sin((float)m_angle * (180 / M_PI));
		interval[1] = vecDir.x * sin((float)m_angle * (180 / M_PI)) + vecDir.y * cos((float)m_angle * (180 / M_PI));

		m_angle = (m_angle + 30) % 360;

		PLAYBACK_EVENT_FULL(0, NULL, m_usEvent, 0, pev->origin, m_vSmokeDetonate, interval[0], interval[1], maxSmokePuffs, 4, m_bLightSmoke, 6);
	}
	else
	{
		UTIL_Bubbles(pev->origin - Vector(64, 64, 64), pev->origin + Vector(64, 64, 64), 100);
	}

	if (m_SGSmoke <= 20)
	{
		pev->nextthink = gpGlobals->time + 1.0;
		SetThink(&CGrenade::SG_Smoke);

		m_SGSmoke++;
	}
	else
	{
		pev->effects |= EF_NODRAW;

		// TODO: Implement me
		// TheBots->CBotManager::RemoveGrenade( this );

		UTIL_Remove(this);
	}
}
Пример #6
0
void CSunOfGod::Animate( void )
{
	entvars_t *pevOwner = VARS( pev->owner );

	if ( UTIL_PointContents(pev->origin) == CONTENT_WATER )
	{
		FX_Trail( pev->origin, entindex(), PROJ_SUNOFGOD_DETONATE_WATER );
		::RadiusDamage( pev->origin, pev, pevOwner, pev->dmg/3, pev->dmg/3, CLASS_NONE, DMG_NUKE | DMG_NEVERGIB);
		UTIL_Remove( this );
		return;
	}

	::RadiusDamage( pev->origin, pev, pevOwner, pev->dmg/50, 180, CLASS_NONE, DMG_NUKE | DMG_NEVERGIB);
	pev->frags--;

	if (pev->frags <= 0)
	Detonate( );
	pev->nextthink = gpGlobals->time + 0.1;
}
Пример #7
0
void CGrenade::Smoke(void)
{
	if (UTIL_PointContents(pev->origin) != CONTENTS_WATER)
	{
		MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin);
		WRITE_BYTE(TE_SMOKE);
		WRITE_COORD(pev->origin.x);
		WRITE_COORD(pev->origin.y);
		WRITE_COORD(pev->origin.z);
		WRITE_SHORT(g_sModelIndexSmoke);
		WRITE_BYTE(25);
		WRITE_BYTE(6);
		MESSAGE_END();
	}
	else
		UTIL_Bubbles(pev->origin - Vector(64, 64, 64), pev->origin + Vector(64, 64, 64), 100);

	UTIL_Remove(this);
}
Пример #8
0
void CGrenade::Smoke3_A(void)
{
	if (UTIL_PointContents(pev->origin) != CONTENTS_WATER)
	{
		MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin);
		WRITE_BYTE(TE_SMOKE);
		WRITE_COORD(pev->origin.x + RANDOM_FLOAT(-128, 128));
		WRITE_COORD(pev->origin.y + RANDOM_FLOAT(-128, 128));
		WRITE_COORD(pev->origin.z + RANDOM_FLOAT(-10, 10));
		WRITE_SHORT(g_sModelIndexSmoke);
		WRITE_BYTE(15 + RANDOM_FLOAT(0, 10));
		WRITE_BYTE(12);
		MESSAGE_END();
	}
	else
		UTIL_Bubbles(pev->origin - Vector(64, 64, 64), pev->origin + Vector(64, 64, 64), 100);

	UTIL_Remove(this);
}
Пример #9
0
void CShockBeam::Explode()
{
	const Contents contents = UTIL_PointContents( GetAbsOrigin() );

	if( m_pSprite )
	{
		UTIL_Remove( m_pSprite );
		m_pSprite = nullptr;
	}

	if( m_pBeam1 )
	{
		UTIL_Remove( m_pBeam1 );
		m_pBeam1 = nullptr;
	}

	if( m_pBeam2 )
	{
		UTIL_Remove( m_pBeam2 );
		m_pBeam2 = nullptr;
	}

	SetDamage( 40 );

	MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, GetAbsOrigin() );
	WRITE_BYTE( TE_DLIGHT );
	WRITE_COORD_VECTOR( GetAbsOrigin() );
	WRITE_BYTE( 8 );
	WRITE_BYTE( 0 );
	WRITE_BYTE( 253 );
	WRITE_BYTE( 253 );
	WRITE_BYTE( 5 );
	WRITE_BYTE( 10 );
	MESSAGE_END();

	SetOwner( nullptr );

	EMIT_SOUND_DYN(
		this, CHAN_WEAPON,
		"weapons/shock_impact.wav",
		UTIL_RandomFloat( 0.8, 0.9 ), ATTN_NORM, 0, PITCH_NORM );
}
Пример #10
0
void CGrenade::Smoke3_B(void)
{
	if (UTIL_PointContents(pev->origin) != CONTENTS_WATER)
	{
		MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin);
		WRITE_BYTE(TE_SMOKE);
		WRITE_COORD(pev->origin.x + RANDOM_FLOAT(-128, 128));
		WRITE_COORD(pev->origin.y + RANDOM_FLOAT(-128, 128));
		WRITE_COORD(pev->origin.z + RANDOM_FLOAT(-10, 10));
		WRITE_SHORT(g_sModelIndexSmoke);
		WRITE_BYTE(15 + RANDOM_FLOAT(0, 10));
		WRITE_BYTE(10);
		MESSAGE_END();
	}
	else
		UTIL_Bubbles(pev->origin - Vector(64, 64, 64), pev->origin + Vector(64, 64, 64), 100);

	pev->nextthink = gpGlobals->time + 0.15;
	SetThink(&CGrenade::Smoke3_A);
}
Пример #11
0
void CGrenade::Smoke( void )
{
	if (UTIL_PointContents ( pev->origin ) == CONTENTS_WATER)
	{
		UTIL_Bubbles( pev->origin - Vector( 64, 64, 64 ), pev->origin + Vector( 64, 64, 64 ), 100 );
	}
	else
	{
		MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
			WRITE_BYTE( TE_SMOKE );
			WRITE_COORD( pev->origin.x );
			WRITE_COORD( pev->origin.y );
			WRITE_COORD( pev->origin.z );
			WRITE_SHORT( g_sModelIndexSmoke );
			WRITE_BYTE( (pev->dmg - 50) * 0.80 ); // scale * 10
			WRITE_BYTE( 12  ); // framerate
		MESSAGE_END();
	}
	UTIL_Remove( this );
}
Пример #12
0
void CBaseGrenade::Smoke( void )
{
	Vector vecAbsOrigin = GetAbsOrigin();
	if ( UTIL_PointContents ( vecAbsOrigin, MASK_WATER ) & MASK_WATER )
	{
		UTIL_Bubbles( vecAbsOrigin - Vector( 64, 64, 64 ), vecAbsOrigin + Vector( 64, 64, 64 ), 100 );
	}
	else
	{
		CPVSFilter filter( vecAbsOrigin );

		te->Smoke( filter, 0.0, 
			&vecAbsOrigin, g_sModelIndexSmoke,
			m_DmgRadius * 0.03,
			24 );
	}
#if !defined( CLIENT_DLL )
	SetThink ( &CBaseGrenade::SUB_Remove );
#endif
	SetNextThink( gpGlobals->curtime );
}
Пример #13
0
//=========================================================
void CQuakeRocket::RocketTouch ( CBaseEntity *pOther )
{
	// Remove if we've hit skybrush
	if ( UTIL_PointContents(pev->origin) == CONTENT_SKY )
	{
		UTIL_Remove( this );
		return;
	}

	// Do touch damage
	float flDmg = RANDOM_FLOAT( 100, 120 );
	CBaseEntity *pOwner = CBaseEntity::Instance(pev->owner);
	if (pOther->pev->health)
		pOther->TakeDamage( pev, pOwner->pev, flDmg, DMG_BULLET );

	// Don't do radius damage to the other, because all the damage was done in the impact
	Q_RadiusDamage(this, pOwner, 120, pOther);

	// Finish and remove
	Explode();
}
Пример #14
0
void CCrossbowBolt::ExplodeThink( void )
{
	int iContents = UTIL_PointContents ( pev->origin );
	int iScale;
	
	pev->dmg = 40;
	iScale = 10;

	MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
		WRITE_BYTE( TE_EXPLOSION);		
		WRITE_COORD( pev->origin.x );
		WRITE_COORD( pev->origin.y );
		WRITE_COORD( pev->origin.z );
		if (iContents != CONTENTS_WATER)
		{
			WRITE_SHORT( g_sModelIndexFireball );
		}
		else
		{
			WRITE_SHORT( g_sModelIndexWExplosion );
		}
		WRITE_BYTE( iScale  ); // scale * 10
		WRITE_BYTE( 15  ); // framerate
		WRITE_BYTE( TE_EXPLFLAG_NONE );
	MESSAGE_END();

	entvars_t *pevOwner;

	if ( pev->owner )
		pevOwner = VARS( pev->owner );
	else
		pevOwner = NULL;

	pev->owner = NULL; // can't traceline attack owner if this is set

	::RadiusDamage( pev->origin, pev, pevOwner, pev->dmg, 128, CLASS_NONE, DMG_BLAST | DMG_ALWAYSGIB );

	UTIL_Remove(this);
}
// Эффект пыли для шагов крематора (аналогично шагам страйдера или охотника, но в меньших масштабах
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;*/
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: Return true if we found a valid placement point
//-----------------------------------------------------------------------------
bool CWeaponBaseCombatObject::GetPlacePosition( CBaseTFPlayer *pBuilder, Vector *vecPlaceOrigin, QAngle *angPlaceAngles )
{
	Vector vecForward;
	QAngle vecAngles = vec3_angle;
	vecAngles.y = pBuilder->EyeAngles().y;
	AngleVectors( vecAngles, &vecForward, NULL, NULL);
	*vecPlaceOrigin = pBuilder->WorldSpaceCenter() + (vecForward * ((m_vecBuildMaxs.x - m_vecBuildMins.x) + 32));
	if ( UTIL_PointContents( *vecPlaceOrigin ) != CONTENTS_EMPTY )
		return false;

	// Room to fit?
	trace_t tr;
	UTIL_TraceHull( *vecPlaceOrigin, *vecPlaceOrigin + Vector(0,0,-64), m_vecBuildMins, m_vecBuildMaxs, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
	if ( tr.allsolid || tr.startsolid )
		return false;
	if ( tr.fraction == 1.0 )
		return false;

	*vecPlaceOrigin = tr.endpos;
	//VectorAngles( tr.plane.normal, *angPlaceAngles );
	*angPlaceAngles = QAngle(0,0,0);
	return true;
}
Пример #17
0
void CGrenade::Smoke( void )
{
	if (UTIL_PointContents ( pev->origin ) == CONTENTS_WATER)
	{
		UTIL_Bubbles( pev->origin - Vector( 64, 64, 64 ), pev->origin + Vector( 64, 64, 64 ), 100 );
	}
	else
	{
		float theDamageModifier;
		int theUpgradeLevel = AvHPlayerUpgrade::GetWeaponUpgrade(this->pev->iuser3, this->pev->iuser4, &theDamageModifier);
		int theDamage = this->pev->dmg*theDamageModifier;
		
		MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
			WRITE_BYTE( TE_SMOKE );
			WRITE_COORD( pev->origin.x );
			WRITE_COORD( pev->origin.y );
			WRITE_COORD( pev->origin.z );
			WRITE_SHORT( g_sModelIndexSmoke );
			WRITE_BYTE( (theDamage - 50) * 0.80 ); // scale * 10
			WRITE_BYTE( 12  ); // framerate
		MESSAGE_END();
	}
	UTIL_Remove( this );
}
Пример #18
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : bool - 
//-----------------------------------------------------------------------------
void C_TEExplosion::PostDataUpdate( DataUpdateType_t updateType )
{
	RecordExplosion();

	AffectRagdolls();

	// Filter out a water explosion
	if ( UTIL_PointContents( m_vecOrigin, MASK_WATER ) & CONTENTS_WATER )
	{
		WaterExplosionEffect().Create( m_vecOrigin, m_nMagnitude, m_fScale, m_nFlags );
		return;
	}

	if ( !( m_nFlags & TE_EXPLFLAG_NOFIREBALL ) )
	{
		if ( CExplosionOverlay *pOverlay = new CExplosionOverlay )
		{
			pOverlay->m_flLifetime	= 0;
			pOverlay->m_vPos		= m_vecOrigin;
			pOverlay->m_nSprites	= 1;
			
			pOverlay->m_vBaseColors[0].Init( 1.0f, 0.9f, 0.7f );

			pOverlay->m_Sprites[0].m_flHorzSize = 0.05f;
			pOverlay->m_Sprites[0].m_flVertSize = pOverlay->m_Sprites[0].m_flHorzSize*0.5f;

			pOverlay->Activate();
		}
	}

	BaseExplosionEffect().Create( m_vecOrigin, m_nMagnitude, m_fScale, m_nFlags );

#ifdef HL2WARS_DLL
	CWarsFlora::DestructFloraInRadius( m_vecOrigin, m_nRadius );
#endif // HL2WARS_DLL
}
Пример #19
0
void CChronosceptor::StartFire()
{
	if (m_pPlayer->pev->waterlevel == 3)
	{
		PlayEmptySound(2);
		m_flNextPrimaryAttack = gpGlobals->time + 0.5;
		return;
	}

	if ( m_fInAttack == 0 )
	{
		m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1;
		return;
	}
	m_iClip--;
	m_iFiredAmmo++;
	FX_FireGun(m_pPlayer->pev->v_angle, m_pPlayer->entindex(), (m_pPlayer->m_fHeavyArmor)?CHRONO_FIRE_SOLID:CHRONO_FIRE, 0, FIREGUN_CHRONOSCEPTOR );
	m_pPlayer->SetAnimation( PLAYER_ATTACK1 );

	Vector vecSrc = m_pPlayer->GetGunPosition( );
	Vector vecDir = gpGlobals->v_forward;

	TraceResult tr;
	UTIL_TraceLine(vecSrc, vecSrc + vecDir * 16384, dont_ignore_monsters, m_pPlayer->edict(), &tr);
	UTIL_MakeVectors(m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle);

	if (UTIL_PointContents(tr.vecEndPos) != CONTENTS_SKY)
	{
		CBlackHole::ShootBlackHole( m_pPlayer->pev, tr.vecEndPos + (tr.vecPlaneNormal * 100));
		EMIT_SOUND(ENT(pev), CHAN_AUTO, "weapons/chronosceptor_blackhole.wav", 1, ATTN_LOW);
	}
	if (!m_pPlayer->m_fHeavyArmor)
	m_pPlayer->pev->punchangle.x -= 3;
	m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1;
	m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1;
}
Пример #20
0
bool CLocalNav::LadderHit(Vector &vecSource, Vector &vecDest, TraceResult &tr)
{
	Vector vecFwd, vecRight, vecUp;
	Vector vecAngles;
	Vector vecOrigin;

	vecAngles = UTIL_VecToAngles(-tr.vecPlaneNormal);
	UTIL_MakeVectorsPrivate(vecAngles, vecFwd, vecRight, vecUp);
	vecOrigin = tr.vecEndPos + (vecFwd * 15) + (vecUp * 36);

	if (UTIL_PointContents(vecOrigin) == CONTENTS_LADDER)
		return true;

	vecOrigin = tr.vecEndPos + (vecFwd * 15) - (vecUp * 36);

	if (UTIL_PointContents(vecOrigin) == CONTENTS_LADDER)
		return true;

	vecOrigin = tr.vecEndPos + (vecFwd * 15) + (vecRight * 16) + (vecUp * 36);

	if (UTIL_PointContents(vecOrigin) == CONTENTS_LADDER)
		return true;

	vecOrigin = tr.vecEndPos + (vecFwd * 15) - (vecRight * 16) + (vecUp * 36);

	if (UTIL_PointContents(vecOrigin) == CONTENTS_LADDER)
		return true;

	vecOrigin = tr.vecEndPos + (vecFwd * 15) + (vecRight * 16) - (vecUp * 36);

	if (UTIL_PointContents(vecOrigin) == CONTENTS_LADDER)
		return true;

	vecOrigin = tr.vecEndPos + (vecFwd * 15) - (vecRight * 16) + (vecUp * 36);

	if (UTIL_PointContents(vecOrigin) == CONTENTS_LADDER)
		return true;

	return false;
}
Пример #21
0
void CCrossbowBolt::BoltTouch( CBaseEntity *pOther )
{
	SetTouch( NULL );
	SetThink( NULL );

	if (pOther->pev->takedamage)
	{
		TraceResult tr = UTIL_GetGlobalTrace( );
		entvars_t	*pevOwner;

		pevOwner = VARS( pev->owner );

		// UNDONE: this needs to call TraceAttack instead
		ClearMultiDamage( );

		if ( pOther->IsPlayer() )
		{
			pOther->TraceAttack(pevOwner, gSkillData.plrDmgCrossbowClient, pev->velocity.Normalize(), &tr, DMG_NEVERGIB ); 
		}
		else
		{
			pOther->TraceAttack(pevOwner, gSkillData.plrDmgCrossbowMonster, pev->velocity.Normalize(), &tr, DMG_BULLET | DMG_NEVERGIB ); 
		}

		ApplyMultiDamage( pev, pevOwner );

		pev->velocity = Vector( 0, 0, 0 );
		// play body "thwack" sound
		switch( RANDOM_LONG(0,1) )
		{
		case 0:
			EMIT_SOUND(ENT(pev), CHAN_BODY, "weapons/xbow_hitbod1.wav", 1, ATTN_NORM); break;
		case 1:
			EMIT_SOUND(ENT(pev), CHAN_BODY, "weapons/xbow_hitbod2.wav", 1, ATTN_NORM); break;
		}

		if ( !g_pGameRules->IsMultiplayer() )
		{
			Killed( pev, GIB_NEVER );
		}
	}
	else
	{
		EMIT_SOUND_DYN(ENT(pev), CHAN_BODY, "weapons/xbow_hit1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 98 + RANDOM_LONG(0,7));

		SetThink( &CCrossbowBolt::SUB_Remove );
		pev->nextthink = gpGlobals->time;// this will get changed below if the bolt is allowed to stick in what it hit.

		if ( FClassnameIs( pOther->pev, "worldspawn" ) )
		{
			// if what we hit is static architecture, can stay around for a while.
			Vector vecDir = pev->velocity.Normalize( );
			UTIL_SetOrigin( pev, pev->origin - vecDir * 12 );
			pev->angles = UTIL_VecToAngles( vecDir );
			pev->solid = SOLID_NOT;
			pev->movetype = MOVETYPE_FLY;
			pev->velocity = Vector( 0, 0, 0 );
			pev->avelocity.z = 0;
			pev->angles.z = RANDOM_LONG(0,360);
			pev->nextthink = gpGlobals->time + 10.0;
		}

		if (UTIL_PointContents(pev->origin) != CONTENTS_WATER)
		{
			UTIL_Sparks( pev->origin );
		}
	}

	if ( g_pGameRules->IsMultiplayer() )
	{
		SetThink( &CCrossbowBolt::ExplodeThink );
		pev->nextthink = gpGlobals->time + 0.1;
	}
}
Пример #22
0
// Add the ability to ignore the world trace
void CSDKGameRules::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore, bool bIgnoreWorld )
{
	CBaseEntity *pEntity = NULL;
	trace_t		tr;
	float		flAdjustedDamage, falloff;
	Vector		vecSpot;
	Vector		vecToTarget;
	Vector		vecEndPos;

	Vector vecSrc = vecSrcIn;

	if ( flRadius )
		falloff = info.GetDamage() / flRadius;
	else
		falloff = 1.0;

	int bInWater = (UTIL_PointContents ( vecSrc ) & MASK_WATER) ? true : false;

	vecSrc.z += 1;// in case grenade is lying on the ground

	// iterate on all entities in the vicinity.
	for ( CEntitySphereQuery sphere( vecSrc, flRadius ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() )
	{
		if ( pEntity->m_takedamage != DAMAGE_NO )
		{
			// UNDONE: this should check a damage mask, not an ignore
			if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore )
			{// houndeyes don't hurt other houndeyes with their attack
				continue;
			}

			// blast's don't tavel into or out of water
			if (bInWater && pEntity->GetWaterLevel() == 0)
				continue;
			if (!bInWater && pEntity->GetWaterLevel() == 3)
				continue;

			// radius damage can only be blocked by the world
			vecSpot = pEntity->BodyTarget( vecSrc );



			bool bHit = false;

			if( bIgnoreWorld )
			{
				vecEndPos = vecSpot;
				bHit = true;
			}
			else
			{
				UTIL_TraceLine( vecSrc, vecSpot, MASK_SOLID_BRUSHONLY, info.GetInflictor(), COLLISION_GROUP_NONE, &tr );

				if (tr.startsolid)
				{
					// if we're stuck inside them, fixup the position and distance
					tr.endpos = vecSrc;
					tr.fraction = 0.0;
				}

				vecEndPos = tr.endpos;

				if( tr.fraction == 1.0 || tr.m_pEnt == pEntity )
				{
					bHit = true;
				}
			}

			if ( bHit )
			{
				// the explosion can 'see' this entity, so hurt them!
				//vecToTarget = ( vecSrc - vecEndPos );
				vecToTarget = ( vecEndPos - vecSrc );

				// decrease damage for an ent that's farther from the bomb.
				flAdjustedDamage = vecToTarget.Length() * falloff;
				flAdjustedDamage = info.GetDamage() - flAdjustedDamage;

				if ( flAdjustedDamage > 0 )
				{
					CTakeDamageInfo adjustedInfo = info;
					adjustedInfo.SetDamage( flAdjustedDamage );

					Vector dir = vecToTarget;
					VectorNormalize( dir );

					// If we don't have a damage force, manufacture one
					if ( adjustedInfo.GetDamagePosition() == vec3_origin || adjustedInfo.GetDamageForce() == vec3_origin )
					{
						CalculateExplosiveDamageForce( &adjustedInfo, dir, vecSrc, 1.5	/* explosion scale! */ );
					}
					else
					{
						// Assume the force passed in is the maximum force. Decay it based on falloff.
						float flForce = adjustedInfo.GetDamageForce().Length() * falloff;
						adjustedInfo.SetDamageForce( dir * flForce );
						adjustedInfo.SetDamagePosition( vecSrc );
					}

					pEntity->TakeDamage( adjustedInfo );

					// Now hit all triggers along the way that respond to damage... 
					pEntity->TraceAttackToTriggers( adjustedInfo, vecSrc, vecEndPos, dir );
				}
			}
		}
	}
}
Пример #23
0
void RadiusDamage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, float flRadius, int iClassIgnore, int bitsDamageType )
{
	CBaseEntity *pEntity = NULL;
	TraceResult	tr;
	float		flAdjustedDamage, falloff;
	Vector		vecSpot;

	if ( flRadius )
		falloff = flDamage / flRadius;
	else
		falloff = 1.0;

	int bInWater = (UTIL_PointContents ( vecSrc ) == CONTENTS_WATER);

	vecSrc.z += 1;// in case grenade is lying on the ground

	if ( !pevAttacker )
		pevAttacker = pevInflictor;

	// iterate on all entities in the vicinity.
	while ((pEntity = UTIL_FindEntityInSphere( pEntity, vecSrc, flRadius )) != NULL)
	{
		if ( pEntity->pev->takedamage != DAMAGE_NO )
		{
			// UNDONE: this should check a damage mask, not an ignore
			if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore )
			{// houndeyes don't hurt other houndeyes with their attack
				continue;
			}

			// blast's don't tavel into or out of water
			if (bInWater && pEntity->pev->waterlevel == 0)
				continue;
			if (!bInWater && pEntity->pev->waterlevel == 3)
				continue;

			vecSpot = pEntity->BodyTarget( vecSrc );
			
			UTIL_TraceLine ( vecSrc, vecSpot, dont_ignore_monsters, ENT(pevInflictor), &tr );

			if ( tr.flFraction == 1.0 || tr.pHit == pEntity->edict() )
			{// the explosion can 'see' this entity, so hurt them!
				if (tr.fStartSolid)
				{
					// if we're stuck inside them, fixup the position and distance
					tr.vecEndPos = vecSrc;
					tr.flFraction = 0.0;
				}
				
				// decrease damage for an ent that's farther from the bomb.
				flAdjustedDamage = ( vecSrc - tr.vecEndPos ).Length() * falloff;
				flAdjustedDamage = flDamage - flAdjustedDamage;
			
				if ( flAdjustedDamage < 0 )
				{
					flAdjustedDamage = 0;
				}
			
				// ALERT( at_console, "hit %s\n", STRING( pEntity->pev->classname ) );
				if (tr.flFraction != 1.0)
				{
					ClearMultiDamage( );
					pEntity->TraceAttack( pevInflictor, flAdjustedDamage, (tr.vecEndPos - vecSrc).Normalize( ), &tr, bitsDamageType );
					ApplyMultiDamage( pevInflictor, pevAttacker );
				}
				else
				{
					pEntity->TakeDamage ( pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType );
				}
			}
		}
	}
}
Пример #24
0
// UNDONE: temporary scorching for PreAlpha - find a less sleazy permenant solution.
void CGrenade::Explode( TraceResult *pTrace, int bitsDamageType )
{
	float		flRndSound;// sound randomizer

	pev->model = iStringNull;//invisible
	pev->solid = SOLID_NOT;// intangible

	pev->takedamage = DAMAGE_NO;

	// Pull out of the wall a bit
	if ( pTrace->flFraction != 1.0 )
	{
		pev->origin = pTrace->vecEndPos + (pTrace->vecPlaneNormal * (pev->dmg - 24) * 0.6);
	}

	int iContents = UTIL_PointContents ( pev->origin );
	
	MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
		WRITE_BYTE( TE_EXPLOSION );		// This makes a dynamic light and the explosion sprites/sound
		WRITE_COORD( pev->origin.x );	// Send to PAS because of the sound
		WRITE_COORD( pev->origin.y );
		WRITE_COORD( pev->origin.z );
		if (iContents != CONTENTS_WATER)
		{
			WRITE_SHORT( g_sModelIndexFireball );
		}
		else
		{
			WRITE_SHORT( g_sModelIndexWExplosion );
		}
		WRITE_BYTE( (pev->dmg - 50) * .60  ); // scale * 10
		WRITE_BYTE( 15  ); // framerate
		WRITE_BYTE( TE_EXPLFLAG_NONE );
	MESSAGE_END();

	CSoundEnt::InsertSound ( bits_SOUND_COMBAT, pev->origin, NORMAL_EXPLOSION_VOLUME, 3.0 );
	entvars_t *pevOwner;
	if ( pev->owner )
		pevOwner = VARS( pev->owner );
	else
		pevOwner = NULL;

	pev->owner = NULL; // can't traceline attack owner if this is set

	RadiusDamage ( pev, pevOwner, pev->dmg, CLASS_NONE, bitsDamageType );

	if ( RANDOM_FLOAT( 0 , 1 ) < 0.5 )
	{
		UTIL_DecalTrace( pTrace, DECAL_SCORCH1 );
	}
	else
	{
		UTIL_DecalTrace( pTrace, DECAL_SCORCH2 );
	}

	flRndSound = RANDOM_FLOAT( 0 , 1 );

	switch ( RANDOM_LONG( 0, 2 ) )
	{
		case 0:	EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/debris1.wav", 0.55, ATTN_NORM);	break;
		case 1:	EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/debris2.wav", 0.55, ATTN_NORM);	break;
		case 2:	EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/debris3.wav", 0.55, ATTN_NORM);	break;
	}

	pev->effects |= EF_NODRAW;
	SetThink( &CGrenade::Smoke );
	pev->velocity = g_vecZero;
	pev->nextthink = gpGlobals->time + 0.3;

	if (iContents != CONTENTS_WATER)
	{
		int sparkCount = RANDOM_LONG(0,3);
		for ( int i = 0; i < sparkCount; i++ )
			Create( "spark_shower", pev->origin, pTrace->vecPlaneNormal, NULL );
	}
}
Пример #25
0
// UNDONE: temporary scorching for PreAlpha - find a less sleazy permenant solution.
void CBaseGrenade::Explode( trace_t *pTrace, int bitsDamageType )
{
#if !defined( CLIENT_DLL )
	
	SetModelName( NULL_STRING );//invisible
	AddSolidFlags( FSOLID_NOT_SOLID );

	m_takedamage = DAMAGE_NO;

	// Pull out of the wall a bit
	if ( pTrace->fraction != 1.0 )
	{
		SetAbsOrigin( pTrace->endpos + (pTrace->plane.normal * 0.6) );
	}

	Vector vecAbsOrigin = GetAbsOrigin();
	int contents = UTIL_PointContents ( vecAbsOrigin, MASK_ALL );



	if ( pTrace->fraction != 1.0 )
	{
		Vector vecNormal = pTrace->plane.normal;
		surfacedata_t *pdata = physprops->GetSurfaceData( pTrace->surface.surfaceProps );	
		CPASFilter filter( vecAbsOrigin );

		te->Explosion( filter, -1.0, // don't apply cl_interp delay
			&vecAbsOrigin,
			!( contents & MASK_WATER ) ? g_sModelIndexFireball : g_sModelIndexWExplosion,
			m_DmgRadius * .03, 
			25,
			TE_EXPLFLAG_NONE|TE_EXPLFLAG_DLIGHT,
			m_DmgRadius,
			m_flDamage,
			&vecNormal,
			(char) pdata->game.material );
	}
	else
	{
		CPASFilter filter( vecAbsOrigin );
		te->Explosion( filter, -1.0, // don't apply cl_interp delay
			&vecAbsOrigin, 
			!( contents & MASK_WATER ) ? g_sModelIndexFireball : g_sModelIndexWExplosion,
			m_DmgRadius * .03, 
			25,
			TE_EXPLFLAG_NONE|TE_EXPLFLAG_DLIGHT,
			m_DmgRadius,
			m_flDamage );
	}

#if !defined( CLIENT_DLL )
	CSoundEnt::InsertSound ( SOUND_COMBAT, GetAbsOrigin(), BASEGRENADE_EXPLOSION_VOLUME, 3.0 );
#endif

	// Use the thrower's position as the reported position
	Vector vecReported = m_hThrower ? m_hThrower->GetAbsOrigin() : vec3_origin;
	
	EmitSound( "BaseGrenade.Explode" );
	CTakeDamageInfo info( this, m_hThrower, GetBlastForce(), GetAbsOrigin(), m_flDamage, bitsDamageType, 0, &vecReported );

	RadiusDamage( info, GetAbsOrigin(), m_DmgRadius, CLASS_NONE, NULL );

	UTIL_DecalTrace( pTrace, "Scorch" );

	SetThink( &CBaseGrenade::SUB_Remove );
	SetTouch( NULL );
	SetSolid( SOLID_NONE );
	
	AddEffects( EF_NODRAW );
	SetAbsVelocity( vec3_origin );

#if HL2_EPISODIC
	// Because the grenade is zipped out of the world instantly, the EXPLOSION sound that it makes for
	// the AI is also immediately destroyed. For this reason, we now make the grenade entity inert and
	// throw it away in 1/10th of a second instead of right away. Removing the grenade instantly causes
	// intermittent bugs with env_microphones who are listening for explosions. They will 'randomly' not
	// hear explosion sounds when the grenade is removed and the SoundEnt thinks (and removes the sound)
	// before the env_microphone thinks and hears the sound.
	SetNextThink( gpGlobals->curtime + 0.1 );
#else
	SetNextThink( gpGlobals->curtime );
#endif//HL2_EPISODIC

#if defined( HL2_DLL )
	CBasePlayer *pPlayer = ToBasePlayer( m_hThrower.Get() );
	if ( pPlayer )
	{
		gamestats->Event_WeaponHit( pPlayer, true, "weapon_frag", info );
	}
#endif

#endif
}
Пример #26
0
void CGrenade::Explode3( TraceResult* pTrace, int bitsDamageType )
{
    pev->model		= iStringNull;	// invisible
    pev->solid		= SOLID_NOT;	// intangible
    pev->takedamage = DAMAGE_NO;

    if( pTrace->flFraction != 1.0 )
    {
        pev->origin = pTrace->vecEndPos + ( pTrace->vecPlaneNormal * ( pev->dmg - 24 ) * 0.6 );
    }

    bool isInWater = UTIL_PointContents( pev->origin ) == CONTENTS_WATER;

    MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
    WRITE_BYTE( TE_EXPLOSION );
    WRITE_COORD( pev->origin.x );
    WRITE_COORD( pev->origin.y );
    WRITE_COORD( pev->origin.z + 20.0 );
    WRITE_SHORT( g_sModelIndexFireball3 );
    WRITE_BYTE( 25 );
    WRITE_BYTE( 30 );
    WRITE_BYTE( 0 );
    MESSAGE_END();

    MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
    WRITE_BYTE( TE_EXPLOSION );
    WRITE_COORD( pev->origin.x + RANDOM_FLOAT( -64, 64 ) );
    WRITE_COORD( pev->origin.y + RANDOM_FLOAT( -64, 64 ) );
    WRITE_COORD( pev->origin.z + RANDOM_FLOAT( 30, 35 ) );
    WRITE_SHORT( g_sModelIndexFireball2 );
    WRITE_BYTE( 30 );
    WRITE_BYTE( 30 );
    WRITE_BYTE( 0 );
    MESSAGE_END();

    CSoundEnt::InsertSound( bits_SOUND_COMBAT, pev->origin, NORMAL_EXPLOSION_VOLUME, 3.0 );

    EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "weapons/c4_explode1.wav", VOL_NORM, 0.25 );

    entvars_t *pevOwner;

    if ( pev->owner )
        pevOwner = VARS( pev->owner );
    else
        pevOwner = NULL;

    pev->owner = NULL; // Can't traceline attack owner if this is set.

// 	TODO: Implements this.
// 	TheBots->OnEvent( EVENT_GRENADE_EXPLODED, pevOwner, NULL );

// 	TODO: Fix me.
// 	CBaseMonster::RadiusDamage( pev, pev, pevOwner, pev->dmg, CLASS_NONE, bitsDamageType );

    UTIL_DecalTrace( pTrace, RANDOM_FLOAT( 0 , 1 ) < 0.5 ? DECAL_SCORCH1 : DECAL_SCORCH2 );

    switch ( RANDOM_LONG( 0, 2 ) )
    {
    case 0:
        EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/debris1.wav", 0.55, ATTN_NORM );
        break;
    case 1:
        EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/debris2.wav", 0.55, ATTN_NORM );
        break;
    case 2:
        EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/debris3.wav", 0.55, ATTN_NORM );
        break;
    }

    pev->effects |= EF_NODRAW;
    SetThink( &CGrenade::Smoke3_C );

    pev->velocity	= g_vecZero;
    pev->nextthink	= gpGlobals->time + 0.55;

    if( !isInWater )
    {
        int sparkCount = RANDOM_LONG( 0, 3 );

        for( int i = 0; i < sparkCount; i++ )
        {
            Create( "spark_shower", pev->origin, pTrace->vecPlaneNormal, NULL );
        }
    }
}
Пример #27
0
void CGrenade::Explode2( TraceResult* pTrace, int bitsDamageType )
{
    pev->model		= iStringNull;	// invisible
    pev->solid		= SOLID_NOT;	// intangible
    pev->takedamage = DAMAGE_NO;

    UTIL_ScreenShake( pTrace->vecEndPos, 25.0, 150.0, 1.0, 3000.0 );

    g_pGameRules->m_bTargetBombed = true;

    if( g_pGameRules->IsCareer() )
    {
        // TODO: implements this.
        // TheCareerTasks->LatchRoundEndMessage();
    }

    m_fJustBlew = TRUE;
    g_pGameRules->CheckWinConditions();

    if( pTrace->flFraction != 1.0 )
    {
        pev->origin = pTrace->vecEndPos + ( pTrace->vecPlaneNormal * ( pev->dmg - 24 ) * 0.6 );
    }

    bool isInWater = UTIL_PointContents( pev->origin ) == CONTENTS_WATER;

    MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
    WRITE_BYTE( TE_SPRITE );
    WRITE_COORD( pev->origin.x );
    WRITE_COORD( pev->origin.y );
    WRITE_COORD( pev->origin.z - 10.0 );
    WRITE_SHORT( g_sModelIndexFireball3 );
    WRITE_BYTE( ( pev->dmg - 275 ) * 0.6 );
    WRITE_BYTE( 150 );
    MESSAGE_END();

    MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
    WRITE_BYTE( TE_SPRITE );
    WRITE_COORD( pev->origin.x + RANDOM_FLOAT( -512, 512 ) );
    WRITE_COORD( pev->origin.y + RANDOM_FLOAT( -512, 512 ) );
    WRITE_COORD( pev->origin.z + RANDOM_FLOAT( -10, 10 ) );
    WRITE_SHORT( g_sModelIndexFireball2 );
    WRITE_BYTE( ( pev->dmg - 275 ) * 0.6 );
    WRITE_BYTE( 150 );
    MESSAGE_END();

    MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
    WRITE_BYTE( TE_SPRITE );
    WRITE_COORD( pev->origin.x + RANDOM_FLOAT( -512, 512 ) );
    WRITE_COORD( pev->origin.y + RANDOM_FLOAT( -512, 512 ) );
    WRITE_COORD( pev->origin.z + RANDOM_FLOAT( -10, 10 ) );
    WRITE_SHORT( g_sModelIndexFireball3 );
    WRITE_BYTE( ( pev->dmg - 275 ) * 0.6 );
    WRITE_BYTE( 150 );
    MESSAGE_END();

    MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
    WRITE_BYTE( TE_SPRITE );
    WRITE_COORD( pev->origin.x + RANDOM_FLOAT( -512, 512 ) );
    WRITE_COORD( pev->origin.y + RANDOM_FLOAT( -512, 512 ) );
    WRITE_COORD( pev->origin.z + RANDOM_FLOAT( -10, 10 ) );
    WRITE_SHORT( g_sModelIndexFireball );
    WRITE_BYTE( ( pev->dmg - 275 ) * 0.6 );
    WRITE_BYTE( 150 );
    MESSAGE_END();

    EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "weapons/c4_explode1.wav", VOL_NORM, 0.25 );

    CSoundEnt::InsertSound( bits_SOUND_COMBAT, pev->origin, NORMAL_EXPLOSION_VOLUME, 3.0 );

    entvars_t *pevOwner;

    if ( pev->owner )
        pevOwner = VARS( pev->owner );
    else
        pevOwner = NULL;

    pev->owner = NULL; // Can't traceline attack owner if this is set.

    // TODO: Fix me.
    //RadiusDamage( pev, pevOwner, pev->dmg, g_pGameRules->m_flBombRadius, CLASS_NONE, bitsDamageType );

    if( g_pGameRules->IsCareer() )
    {
        // TODO: implements this.
        // TheCareerTasks->UnlatchRoundEndMessage();
    }

    MESSAGE_BEGIN( MSG_SPEC, SVC_DIRECTOR );
    WRITE_BYTE( 9 );
    WRITE_BYTE( DRC_CMD_EVENT );
    WRITE_SHORT( ENTINDEX( this->edict() ) );
    WRITE_SHORT( NULL );
    WRITE_ENTITY( DRC_FLAG_FINAL | 15 );
    MESSAGE_END();

    UTIL_DecalTrace( pTrace, RANDOM_FLOAT( 0 , 1 ) < 0.5 ? DECAL_SCORCH1 : DECAL_SCORCH2 );

    switch ( RANDOM_LONG( 0, 2 ) )
    {
    case 0:
        EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/debris1.wav", 0.55, ATTN_NORM );
        break;
    case 1:
        EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/debris2.wav", 0.55, ATTN_NORM );
        break;
    case 2:
        EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/debris3.wav", 0.55, ATTN_NORM );
        break;
    }

    pev->effects |= EF_NODRAW;
    SetThink( &CGrenade::Smoke2 );

    pev->velocity	= g_vecZero;
    pev->nextthink	= gpGlobals->time + 0.85;

    if( !isInWater )
    {
        int sparkCount = RANDOM_LONG( 0, 3 );

        for( int i = 0; i < sparkCount; i++ )
        {
            Create( "spark_shower", pev->origin, pTrace->vecPlaneNormal, NULL );
        }
    }
}
void CHL1BaseGrenade::Explode( trace_t *pTrace, int bitsDamageType )
{
	float		flRndSound;// sound randomizer

	SetModelName( NULL_STRING );//invisible
	AddSolidFlags( FSOLID_NOT_SOLID );

	m_takedamage = DAMAGE_NO;

	// Pull out of the wall a bit
	if ( pTrace->fraction != 1.0 )
	{
		SetLocalOrigin( pTrace->endpos + (pTrace->plane.normal * 0.6) );
	}

	UTIL_Relink( this );

	Vector vecAbsOrigin = GetAbsOrigin();
	int contents = UTIL_PointContents ( vecAbsOrigin );

	if ( pTrace->fraction != 1.0 )
	{
		Vector vecNormal = pTrace->plane.normal;
		surfacedata_t *pdata = physprops->GetSurfaceData( pTrace->surface.surfaceProps );	
		CPASFilter filter( vecAbsOrigin );
		te->Explosion( filter, 0.0, 
			&vecAbsOrigin,
			!( contents & MASK_WATER ) ? g_sModelIndexFireball : g_sModelIndexWExplosion,
			m_DmgRadius * .03, 
			25,
			TE_EXPLFLAG_NONE,
			m_DmgRadius,
			m_flDamage,
			&vecNormal,
			(char) pdata->gameMaterial );
	}
	else
	{
		CPASFilter filter( vecAbsOrigin );
		te->Explosion( filter, 0.0,
			&vecAbsOrigin, 
			!( contents & MASK_WATER ) ? g_sModelIndexFireball : g_sModelIndexWExplosion,
			m_DmgRadius * .03, 
			25,
			TE_EXPLFLAG_NONE,
			m_DmgRadius,
			m_flDamage );
	}

	CSoundEnt::InsertSound ( SOUND_COMBAT, GetAbsOrigin(), BASEGRENADE_EXPLOSION_VOLUME, 3.0 );

	// Use the owner's position as the reported position
	Vector vecReported = GetOwner() ? GetOwner()->GetAbsOrigin() : vec3_origin;
	
	CTakeDamageInfo info( this, GetOwner(), GetBlastForce(), GetAbsOrigin(), m_flDamage, bitsDamageType, 0, &vecReported );

	RadiusDamage( info, GetAbsOrigin(), m_DmgRadius, CLASS_NONE );

	UTIL_DecalTrace( pTrace, "Scorch" );

	flRndSound = random->RandomFloat( 0 , 1 );

	EmitSound( "BaseGrenade.Explode" );

	SetTouch( NULL );
	
	m_fEffects		|= EF_NODRAW;
	SetAbsVelocity( vec3_origin );

	SetThink( Smoke );
	SetNextThink( gpGlobals->curtime + 0.3);

	if ( GetWaterLevel() == 0 )
	{
		int sparkCount = random->RandomInt( 0,3 );
		QAngle angles;
		VectorAngles( pTrace->plane.normal, angles );

		for ( int i = 0; i < sparkCount; i++ )
			Create( "spark_shower", GetAbsOrigin(), angles, NULL );
	}
}
Пример #29
0
void CGameRules::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore )
{
	const int MASK_RADIUS_DAMAGE = MASK_SHOT&(~CONTENTS_HITBOX);
	CBaseEntity *pEntity = NULL;
	trace_t		tr;
	float		flAdjustedDamage, falloff;
	Vector		vecSpot;

	Vector vecSrc = vecSrcIn;

	if ( flRadius )
		falloff = info.GetDamage() / flRadius;
	else
		falloff = 1.0;

	int bInWater = (UTIL_PointContents ( vecSrc ) & MASK_WATER) ? true : false;

#ifdef HL2_DLL
	if( bInWater )
	{
		// Only muffle the explosion if deeper than 2 feet in water.
		if( !(UTIL_PointContents(vecSrc + Vector(0, 0, 24)) & MASK_WATER) )
		{
			bInWater = false;
		}
	}
#endif // HL2_DLL
	
	vecSrc.z += 1;// in case grenade is lying on the ground

	float flHalfRadiusSqr = Square( flRadius / 2.0f );

	// iterate on all entities in the vicinity.
	for ( CEntitySphereQuery sphere( vecSrc, flRadius ); (pEntity = sphere.GetCurrentEntity()) != NULL; sphere.NextEntity() )
	{
		// This value is used to scale damage when the explosion is blocked by some other object.
		float flBlockedDamagePercent = 0.0f;

		if ( pEntity == pEntityIgnore )
			continue;

		if ( pEntity->m_takedamage == DAMAGE_NO )
			continue;

		// UNDONE: this should check a damage mask, not an ignore
		if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore )
		{// houndeyes don't hurt other houndeyes with their attack
			continue;
		}

		// blast's don't tavel into or out of water
		if (bInWater && pEntity->GetWaterLevel() == 0)
			continue;

		if (!bInWater && pEntity->GetWaterLevel() == 3)
			continue;

		// Check that the explosion can 'see' this entity.
		vecSpot = pEntity->BodyTarget( vecSrc, false );
		UTIL_TraceLine( vecSrc, vecSpot, MASK_RADIUS_DAMAGE, info.GetInflictor(), COLLISION_GROUP_NONE, &tr );

		if( old_radius_damage.GetBool() )
		{
			if ( tr.fraction != 1.0 && tr.m_pEnt != pEntity )
			continue;
		}
		else
		{
			if ( tr.fraction != 1.0 )
			{
				if ( IsExplosionTraceBlocked(&tr) )
				{
					if( ShouldUseRobustRadiusDamage( pEntity ) )
					{
						if( vecSpot.DistToSqr( vecSrc ) > flHalfRadiusSqr )
						{
							// Only use robust model on a target within one-half of the explosion's radius.
							continue;
						}

						Vector vecToTarget = vecSpot - tr.endpos;
						VectorNormalize( vecToTarget );

						// We're going to deflect the blast along the surface that 
						// interrupted a trace from explosion to this target.
						Vector vecUp, vecDeflect;
						CrossProduct( vecToTarget, tr.plane.normal, vecUp );
						CrossProduct( tr.plane.normal, vecUp, vecDeflect );
						VectorNormalize( vecDeflect );

						// Trace along the surface that intercepted the blast...
						UTIL_TraceLine( tr.endpos, tr.endpos + vecDeflect * ROBUST_RADIUS_PROBE_DIST, MASK_RADIUS_DAMAGE, info.GetInflictor(), COLLISION_GROUP_NONE, &tr );
						//NDebugOverlay::Line( tr.startpos, tr.endpos, 255, 255, 0, false, 10 );

						// ...to see if there's a nearby edge that the explosion would 'spill over' if the blast were fully simulated.
						UTIL_TraceLine( tr.endpos, vecSpot, MASK_RADIUS_DAMAGE, info.GetInflictor(), COLLISION_GROUP_NONE, &tr );
						//NDebugOverlay::Line( tr.startpos, tr.endpos, 255, 0, 0, false, 10 );

						if( tr.fraction != 1.0 && tr.DidHitWorld() )
						{
							// Still can't reach the target.
							continue;
						}
						// else fall through
					}
					else
					{
						continue;
					}
				}

				// UNDONE: Probably shouldn't let children block parents either?  Or maybe those guys should set their owner if they want this behavior?
				// HL2 - Dissolve damage is not reduced by interposing non-world objects
				if( tr.m_pEnt && tr.m_pEnt != pEntity && tr.m_pEnt->GetOwnerEntity() != pEntity )
				{
					// Some entity was hit by the trace, meaning the explosion does not have clear
					// line of sight to the entity that it's trying to hurt. If the world is also
					// blocking, we do no damage.
					CBaseEntity *pBlockingEntity = tr.m_pEnt;
					//Msg( "%s may be blocked by %s...", pEntity->GetClassname(), pBlockingEntity->GetClassname() );

					UTIL_TraceLine( vecSrc, vecSpot, CONTENTS_SOLID, info.GetInflictor(), COLLISION_GROUP_NONE, &tr );

					if( tr.fraction != 1.0 )
					{
						continue;
					}
					
					// Now, if the interposing object is physics, block some explosion force based on its mass.
					if( pBlockingEntity->VPhysicsGetObject() )
					{
						const float MASS_ABSORB_ALL_DAMAGE = 350.0f;
						float flMass = pBlockingEntity->VPhysicsGetObject()->GetMass();
						float scale = flMass / MASS_ABSORB_ALL_DAMAGE;

						// Absorbed all the damage.
						if( scale >= 1.0f )
						{
							continue;
						}

						ASSERT( scale > 0.0f );
						flBlockedDamagePercent = scale;
						//Msg("  Object (%s) weighing %fkg blocked %f percent of explosion damage\n", pBlockingEntity->GetClassname(), flMass, scale * 100.0f);
					}
					else
					{
						// Some object that's not the world and not physics. Generically block 25% damage
						flBlockedDamagePercent = 0.25f;
					}
				}
			}
		}
		// decrease damage for an ent that's farther from the bomb.
		flAdjustedDamage = ( vecSrc - tr.endpos ).Length() * falloff;
		flAdjustedDamage = info.GetDamage() - flAdjustedDamage;

		if ( flAdjustedDamage <= 0 )
		{
			continue;
		}

		// the explosion can 'see' this entity, so hurt them!
		if (tr.startsolid)
		{
			// if we're stuck inside them, fixup the position and distance
			tr.endpos = vecSrc;
			tr.fraction = 0.0;
		}
		
		CTakeDamageInfo adjustedInfo = info;
		//Msg("%s: Blocked damage: %f percent (in:%f  out:%f)\n", pEntity->GetClassname(), flBlockedDamagePercent * 100, flAdjustedDamage, flAdjustedDamage - (flAdjustedDamage * flBlockedDamagePercent) );
		adjustedInfo.SetDamage( flAdjustedDamage - (flAdjustedDamage * flBlockedDamagePercent) );

		// Now make a consideration for skill level!
		if( info.GetAttacker() && info.GetAttacker()->IsPlayer() && pEntity->IsNPC() )
		{
			// An explosion set off by the player is harming an NPC. Adjust damage accordingly.
			adjustedInfo.AdjustPlayerDamageInflictedForSkillLevel();
		}

		Vector dir = vecSpot - vecSrc;
		VectorNormalize( dir );

		// If we don't have a damage force, manufacture one
		if ( adjustedInfo.GetDamagePosition() == vec3_origin || adjustedInfo.GetDamageForce() == vec3_origin )
		{
			if ( !( adjustedInfo.GetDamageType() & DMG_PREVENT_PHYSICS_FORCE ) )
			{
				CalculateExplosiveDamageForce( &adjustedInfo, dir, vecSrc );
			}
		}
		else
		{
			// Assume the force passed in is the maximum force. Decay it based on falloff.
			float flForce = adjustedInfo.GetDamageForce().Length() * falloff;
			adjustedInfo.SetDamageForce( dir * flForce );
			adjustedInfo.SetDamagePosition( vecSrc );
		}

		if ( tr.fraction != 1.0 && pEntity == tr.m_pEnt )
		{
			ClearMultiDamage( );
			pEntity->DispatchTraceAttack( adjustedInfo, dir, &tr );
			ApplyMultiDamage();
		}
		else
		{
			pEntity->TakeDamage( adjustedInfo );
		}

		// Now hit all triggers along the way that respond to damage... 
		pEntity->TraceAttackToTriggers( adjustedInfo, vecSrc, tr.endpos, dir );

#if defined( GAME_DLL )
		if ( info.GetAttacker() && info.GetAttacker()->IsPlayer() && ToBaseCombatCharacter( tr.m_pEnt ) )
		{

			// This is a total hack!!!
			bool bIsPrimary = true;
			CBasePlayer *player = ToBasePlayer( info.GetAttacker() );
			CBaseCombatWeapon *pWeapon = player->GetActiveWeapon();
			if ( pWeapon && FClassnameIs( pWeapon, "weapon_smg1" ) )
			{
				bIsPrimary = false;
			}

			//gamestats->Event_WeaponHit( player, bIsPrimary, (pWeapon != NULL) ? player->GetActiveWeapon()->GetClassname() : "NULL", info );
		}
#endif
	}
}
Пример #30
0
void RadiusFlash(
    Vector vecSrc,
    CBaseEntity *pevInflictor,
    CBaseEntity *pevAttacker,
    float flDamage,
    int iClassIgnore,
    int bitsDamageType)
{
    vecSrc.z += 1;// in case grenade is lying on the ground

    if (!pevAttacker)
        pevAttacker = pevInflictor;

    trace_t		tr;
    float		flAdjustedDamage;
    variant_t	var;
    Vector		vecEyePos;
    float		fadeTime, fadeHold;
    Vector		vForward;
    Vector		vecLOS;
    float		flDot;

    CBaseEntity		*pEntity = NULL;
    static float	flRadius = 1500;
    float			falloff = flDamage / flRadius;

    bool bInWater = (UTIL_PointContents(vecSrc) == CONTENTS_WATER);

    // iterate on all entities in the vicinity.
    while ((pEntity = gEntList.FindEntityInSphere(pEntity, vecSrc, flRadius)) != NULL)
    {
        bool bPlayer = pEntity->IsPlayer();
        bool bHostage = (Q_stricmp(pEntity->GetClassname(), "hostage_entity") == 0);

        if (!bPlayer && !bHostage)
            continue;

        vecEyePos = pEntity->EyePosition();

        // blasts don't travel into or out of water
        if (bInWater && pEntity->GetWaterLevel() == 0)
            continue;
        if (!bInWater && pEntity->GetWaterLevel() == 3)
            continue;

        float percentageOfFlash = PercentageOfFlashForPlayer(pEntity, vecSrc, pevInflictor);

        if (percentageOfFlash > 0.0)
        {
            // decrease damage for an ent that's farther from the grenade
            flAdjustedDamage = flDamage - (vecSrc - pEntity->EyePosition()).Length() * falloff;

            if (flAdjustedDamage > 0)
            {
                // See if we were facing the flash
                AngleVectors(pEntity->EyeAngles(), &vForward);

                vecLOS = (vecSrc - vecEyePos);

                //float flDistance = vecLOS.Length();

                // Normalize both vectors so the dotproduct is in the range -1.0 <= x <= 1.0 
                vecLOS.NormalizeInPlace();

                flDot = DotProduct(vecLOS, vForward);

                float startingAlpha = 255;

                // if target is facing the bomb, the effect lasts longer
                if (flDot >= 0.5)
                {
                    // looking at the flashbang
                    fadeTime = flAdjustedDamage * 2.5f;
                    fadeHold = flAdjustedDamage * 1.25f;
                }
                else if (flDot >= -0.5)
                {
                    // looking to the side
                    fadeTime = flAdjustedDamage * 1.75f;
                    fadeHold = flAdjustedDamage * 0.8f;
                }
                else
                {
                    // facing away
                    fadeTime = flAdjustedDamage * 1.0f;
                    fadeHold = flAdjustedDamage * 0.75f;
                    startingAlpha = 200;
                }

                fadeTime *= percentageOfFlash;
                fadeHold *= percentageOfFlash;

                if (bPlayer)
                {
                    //MOM_TODO: do we want this functionality?
                    // blind players and bots
                    //CMomentumPlayer *player = static_cast<CMomentumPlayer *>(pEntity);
                    //player->Blind( fadeHold, fadeTime, startingAlpha );

                    // deafen players and bots
                    //player->Deafen( flDistance );
                }
                else if (bHostage)
                {
                    variant_t val;
                    val.SetFloat(fadeTime);
                    pEntity->AcceptInput("flashbang", pevInflictor, pevAttacker, val, 0);
                }
            }
        }
    }

    CPVSFilter filter(vecSrc);
    te->DynamicLight(filter, 0.0, &vecSrc, 255, 255, 255, 2, 400, 0.1, 768);
}