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.
239 lines
6.8 KiB
239 lines
6.8 KiB
//========= 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 = 1e16; |
|
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(); |
|
} |
|
|
|
|