|
|
|
//========= 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();
|
|
|
|
}
|
|
|
|
|