Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
6.8 KiB

5 years ago
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "tf_obj_barbed_wire.h"
#include "tf_player.h"
#include "basetfvehicle.h"
#include "engine/IEngineSound.h"
#include "te_effect_dispatch.h"
#include "ndebugoverlay.h"
#define BARBED_WIRE_MINS Vector(-5, -5, 0)
#define BARBED_WIRE_MAXS Vector( 5, 5, 40)
#define BARBED_WIRE_MODEL "models/objects/obj_barbed_wire.mdl"
#define MAX_BARBED_WIRE_DISTANCE 768
#define BARBED_WIRE_THINK_CONTEXT "BarbedWireThinkContext"
#define BARBED_WIRE_THINK_INTERVAL 0.2
ConVar obj_barbed_wire_damage( "obj_barbed_wire_damage", "80" );
ConVar obj_barbed_wire_health( "obj_barbed_wire_health", "100" );
IMPLEMENT_SERVERCLASS_ST( CObjectBarbedWire, DT_ObjectBarbedWire )
SendPropEHandle( SENDINFO( m_hConnectedTo ) )
END_SEND_TABLE()
LINK_ENTITY_TO_CLASS( obj_barbed_wire, CObjectBarbedWire );
PRECACHE_REGISTER( obj_barbed_wire );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CObjectBarbedWire::CObjectBarbedWire()
{
m_iHealth = obj_barbed_wire_health.GetInt();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CObjectBarbedWire::Precache()
{
PrecacheModel( BARBED_WIRE_MODEL );
BaseClass::Precache();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CObjectBarbedWire::Spawn()
{
Precache();
SetModel( BARBED_WIRE_MODEL );
SetSolid( SOLID_BBOX );
SetType( OBJ_BARBED_WIRE );
UTIL_SetSize(this, BARBED_WIRE_MINS, BARBED_WIRE_MAXS );
// Set our flags.
m_fObjectFlags |= OF_DOESNT_NEED_POWER | OF_SUPPRESS_APPEAR_ON_MINIMAP | OF_SUPPRESS_NOTIFY_UNDER_ATTACK | OF_ALLOW_REPEAT_PLACEMENT;
// Get the ball rolling here.
BarbedWireThink();
BaseClass::Spawn();
}
//-----------------------------------------------------------------------------
// Purpose: Enumerator
//-----------------------------------------------------------------------------
class CBarbedWireEnumerator : public IEntityEnumerator
{
public:
CBarbedWireEnumerator( CObjectBarbedWire *pWire, Ray_t *pRay, int contentsMask )
{
m_pWire = pWire;
m_pRay = pRay;
m_ContentsMask = contentsMask;
m_aDamagedEntities.Purge();
}
virtual bool EnumEntity( IHandleEntity *pHandleEntity )
{
CBaseEntity *pEntity = gEntList.GetBaseEntity( pHandleEntity->GetRefEHandle() );
if ( pEntity && !m_pWire->InSameTeam( pEntity ) )
{
trace_t tr;
enginetrace->ClipRayToEntity( *m_pRay, m_ContentsMask, pHandleEntity, &tr );
if ( tr.fraction < 1.0f )
{
// Add them to the list & damage them later.
// Done this way so entities don't remove themselves from leaves while we're tracing
if ( m_aDamagedEntities.Find( pEntity ) == m_aDamagedEntities.InvalidIndex() )
{
m_aDamagedEntities.AddToTail( pEntity );
}
}
}
return true;
}
void DamageEntities( void )
{
int iSize = m_aDamagedEntities.Count();
for ( int i = iSize-1; i >= 0; i-- )
{
CBaseEntity *pEntity = m_aDamagedEntities[i].Get();
if ( pEntity )
{
// DMG_CRUSH added so there's no physics force generated
CTakeDamageInfo info( m_pWire, m_pWire->GetBuilder(), obj_barbed_wire_damage.GetFloat() * BARBED_WIRE_THINK_INTERVAL, DMG_SLASH | DMG_CRUSH );
pEntity->TakeDamage( info );
// Bloodspray
CEffectData data;
data.m_vOrigin = pEntity->WorldSpaceCenter();
data.m_vNormal = Vector(0,0,1);
data.m_flScale = 4;
data.m_fFlags = FX_BLOODSPRAY_ALL;
data.m_nEntIndex = pEntity->entindex();
DispatchEffect( "tf2blood", data );
}
}
}
private:
CObjectBarbedWire *m_pWire;
int m_ContentsMask;
Ray_t
*m_pRay;
CUtlVector< EHANDLE > m_aDamagedEntities;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CObjectBarbedWire::BarbedWireThink( void )
{
// Cut the rope if we're too far from the entity it's attached to.
if ( m_hConnectedTo.Get() )
{
if ( (WorldSpaceCenter() - m_hConnectedTo->WorldSpaceCenter()).Length() > MAX_BARBED_WIRE_DISTANCE )
{
m_hConnectedTo = NULL;
}
if ( m_hConnectedTo )
{
Ray_t ray;
ray.Init( WorldSpaceCenter(), m_hConnectedTo->WorldSpaceCenter() );
//NDebugOverlay::Line( WorldSpaceCenter(), m_hConnectedTo->WorldSpaceCenter(), 255,255,255, false, 0.1 );
//NDebugOverlay::Box( WorldSpaceCenter(), -Vector(5,5,5), Vector(5,5,5), 0,255,0,8, 0.1 );
//NDebugOverlay::Box( m_hConnectedTo->WorldSpaceCenter(), -Vector(6,6,6), Vector(6,6,6), 255,255,255,8, 0.1 );
CBarbedWireEnumerator bwEnum( this, &ray, MASK_SHOT_HULL );
enginetrace->EnumerateEntities( ray, false, &bwEnum );
bwEnum.DamageEntities();
}
}
SetContextThink( BarbedWireThink, gpGlobals->curtime + BARBED_WIRE_THINK_INTERVAL, BARBED_WIRE_THINK_CONTEXT );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CObjectBarbedWire::StartPlacement( CBaseTFPlayer *pPlayer )
{
if ( pPlayer && !m_hConnectedTo )
{
// Automatically connect to the nearest barbed wire on our team.
float flClosest = 1e24;
CObjectBarbedWire *pClosest = NULL;
CBaseEntity *pCur = gEntList.FirstEnt();
while ( pCur )
{
CObjectBarbedWire *pWire = dynamic_cast< CObjectBarbedWire* >( pCur );
if ( pWire )
{
if ( pWire->GetTeamNumber() == pPlayer->GetTeamNumber() )
{
float flDist = (pWire->WorldSpaceCenter() - pPlayer->WorldSpaceCenter()).Length();
if ( flDist < flClosest )
{
flClosest = flDist;
pClosest = pWire;
}
}
}
pCur = gEntList.NextEnt( pCur );
}
if ( pClosest )
{
m_hConnectedTo = pClosest;
}
}
BaseClass::StartPlacement( pPlayer );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CObjectBarbedWire::PreStartBuilding()
{
const CObjectBarbedWire *pWire = dynamic_cast< const CObjectBarbedWire* >( m_hBuiltOnEntity.Get() );
if ( pWire )
{
// Reconnect the wire to this entity and don't build yet.
m_hConnectedTo = pWire;
return false;
}
else
{
// Go ahead and build.
return true;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CObjectBarbedWire::FinishedBuilding()
{
BaseClass::FinishedBuilding();
}