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.
400 lines
12 KiB
400 lines
12 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose: Func door that's weldable shut
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//=============================================================================//
|
||
|
#include "cbase.h"
|
||
|
#include "beam_shared.h"
|
||
|
#include "tf_player.h"
|
||
|
#include "tf_team.h"
|
||
|
#include "tf_basecombatweapon.h"
|
||
|
#include "tf_func_weldable_door.h"
|
||
|
#include "IEffects.h"
|
||
|
|
||
|
|
||
|
LINK_ENTITY_TO_CLASS( func_door_weldable, CWeldableDoor );
|
||
|
|
||
|
BEGIN_DATADESC( CWeldableDoor )
|
||
|
|
||
|
// keys
|
||
|
DEFINE_KEYFIELD( m_iszWeldPoints, FIELD_STRING, "weldpoints" ),
|
||
|
|
||
|
END_DATADESC()
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeldableDoor::Spawn( void )
|
||
|
{
|
||
|
BaseClass::Spawn();
|
||
|
|
||
|
m_hWeldingPlayer = NULL;
|
||
|
m_flMaxWeldedPercentage = 0.0;
|
||
|
m_iWeldLeader = WL_UNASSIGNED;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeldableDoor::Activate( void )
|
||
|
{
|
||
|
BaseClass::Activate();
|
||
|
|
||
|
// Find my weld points
|
||
|
if ( !m_iszWeldPoints )
|
||
|
{
|
||
|
Msg( "func_weldable_door without weldpoints specified.\n" );
|
||
|
UTIL_Remove( this );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Find the weld points. Doors will almost always have multiple weld point pairs.
|
||
|
CWeldPoint *pWeldStartPoint = NULL;
|
||
|
while( (pWeldStartPoint = (CWeldPoint*)gEntList.FindEntityByName( pWeldStartPoint, m_iszWeldPoints ) ) != NULL )
|
||
|
{
|
||
|
// Does it have an endpoint specified?
|
||
|
if ( !pWeldStartPoint->m_target )
|
||
|
{
|
||
|
Msg( "func_weldable_door weldpoint '%s' didn't have an endpoint specified.\n", STRING(m_iszWeldPoints) );
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Find the endpoint for this startpoint
|
||
|
CWeldPoint *pWeldEndPoint = (CWeldPoint*)gEntList.FindEntityByName( NULL, pWeldStartPoint->m_target );
|
||
|
if ( pWeldEndPoint )
|
||
|
{
|
||
|
// Connect the start point to the endpoint
|
||
|
pWeldStartPoint->SetEndPoint( pWeldEndPoint->GetLocalOrigin() );
|
||
|
|
||
|
// Add it to the list
|
||
|
m_aWeldPoints.AddToTail( pWeldStartPoint );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Msg( "func_weldable_door weldpoint couldn't find it's endpoint of '%s'.\n", STRING(pWeldStartPoint->m_target) );
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Did we find any weldpoint pairs?
|
||
|
if ( m_aWeldPoints.Size() == 0 )
|
||
|
{
|
||
|
Msg( "func_weldable_door couldn't find any weldpoints for '%s'.\n", STRING(m_iszWeldPoints) );
|
||
|
UTIL_Remove( this );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Returns true if someone's allowed to start welding on this door
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CWeldableDoor::IsWeldable( CBaseTFPlayer *pWeldee )
|
||
|
{
|
||
|
// Can't be welded if I'm open
|
||
|
if ( m_toggle_state != TS_AT_BOTTOM )
|
||
|
return false;
|
||
|
|
||
|
// Can't be welded if I'm already being welded by someone else
|
||
|
if ( m_hWeldingPlayer != NULL && (((CBaseEntity*)m_hWeldingPlayer) != pWeldee) )
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Return the weld leader.
|
||
|
// Doors can be made up of multiple door entities, so one of them needs to volunteer to control the welding.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CWeldableDoor *CWeldableDoor::GetWeldLeader( void )
|
||
|
{
|
||
|
// Am I the leader?
|
||
|
if ( m_iWeldLeader == WL_WELD_LEADER )
|
||
|
return this;
|
||
|
|
||
|
// If this guy's unassigned, he's volunteering
|
||
|
if ( m_iWeldLeader == WL_UNASSIGNED )
|
||
|
{
|
||
|
m_iWeldLeader = WL_WELD_LEADER;
|
||
|
|
||
|
// Tell all other friends they're children
|
||
|
CBaseEntity *pTarget = NULL;
|
||
|
if ( GetEntityName() != NULL_STRING )
|
||
|
{
|
||
|
while ( (pTarget = gEntList.FindEntityByName( pTarget, GetEntityName() )) != NULL )
|
||
|
{
|
||
|
if ( pTarget != this )
|
||
|
{
|
||
|
CWeldableDoor *pWeldableDoor = dynamic_cast< CWeldableDoor * >( pTarget );
|
||
|
if ( pWeldableDoor )
|
||
|
{
|
||
|
pWeldableDoor->m_iWeldLeader = WL_WELD_CHILD;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
// We're not the leader. so find him
|
||
|
CBaseEntity *pTarget = NULL;
|
||
|
if ( GetEntityName() != NULL_STRING )
|
||
|
{
|
||
|
while ( (pTarget = gEntList.FindEntityByName( pTarget, GetEntityName() )) != NULL )
|
||
|
{
|
||
|
if ( pTarget != this )
|
||
|
{
|
||
|
CWeldableDoor *pWeldableDoor = dynamic_cast< CWeldableDoor * >( pTarget );
|
||
|
if ( pWeldableDoor && pWeldableDoor->m_iWeldLeader == WL_WELD_LEADER )
|
||
|
return pWeldableDoor;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: The Player's going to start welding this door.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeldableDoor::StartWelding( CBaseTFPlayer *pWeldee )
|
||
|
{
|
||
|
m_hWeldingPlayer = pWeldee;
|
||
|
|
||
|
// If this is the weld leader, tell all the door pieces that the player's welding them
|
||
|
if ( m_iWeldLeader == WL_WELD_LEADER )
|
||
|
{
|
||
|
CBaseEntity *pTarget = NULL;
|
||
|
if ( GetEntityName() != NULL_STRING )
|
||
|
{
|
||
|
while ( (pTarget = gEntList.FindEntityByName( pTarget, GetEntityName() )) != NULL )
|
||
|
{
|
||
|
if ( pTarget != this )
|
||
|
{
|
||
|
CWeldableDoor *pWeldableDoor = dynamic_cast< CWeldableDoor * >( pTarget );
|
||
|
if ( pWeldableDoor )
|
||
|
{
|
||
|
pWeldableDoor->StartWelding( pWeldee );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: The player's stopped welding this door
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeldableDoor::StopWelding( void )
|
||
|
{
|
||
|
m_hWeldingPlayer = NULL;
|
||
|
|
||
|
// If this is the weld leader, tell all the door pieces that the player's stopped welding them
|
||
|
if ( m_iWeldLeader == WL_WELD_LEADER )
|
||
|
{
|
||
|
CBaseEntity *pTarget = NULL;
|
||
|
if ( GetEntityName() != NULL_STRING )
|
||
|
{
|
||
|
while ( (pTarget = gEntList.FindEntityByName( pTarget, GetEntityName() )) != NULL )
|
||
|
{
|
||
|
if ( pTarget != this )
|
||
|
{
|
||
|
CWeldableDoor *pWeldableDoor = dynamic_cast< CWeldableDoor * >( pTarget );
|
||
|
if ( pWeldableDoor )
|
||
|
{
|
||
|
pWeldableDoor->StopWelding();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Return the amount the door's been welded
|
||
|
//-----------------------------------------------------------------------------
|
||
|
float CWeldableDoor::GetWeldPercentage( void )
|
||
|
{
|
||
|
return m_flWeldedPercentage;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Update the amount the door's been welded
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeldableDoor::UpdateWeld( bool bCutting, float flWeldPercentage )
|
||
|
{
|
||
|
if ( m_flMaxWeldedPercentage < flWeldPercentage )
|
||
|
m_flMaxWeldedPercentage = flWeldPercentage;
|
||
|
m_flWeldedPercentage = flWeldPercentage;
|
||
|
|
||
|
// Did we cut away the entire weld?
|
||
|
if ( m_flWeldedPercentage <= 0.0 )
|
||
|
{
|
||
|
// Clear welded
|
||
|
m_flMaxWeldedPercentage = 0.0;
|
||
|
|
||
|
if ( m_bLocked )
|
||
|
{
|
||
|
// Unlock all the pieces of this door
|
||
|
m_bLocked = false;
|
||
|
|
||
|
CBaseEntity *pTarget = NULL;
|
||
|
if ( GetEntityName() != NULL_STRING )
|
||
|
{
|
||
|
while ( (pTarget = gEntList.FindEntityByName( pTarget, GetEntityName() )) != NULL )
|
||
|
{
|
||
|
if ( pTarget != this )
|
||
|
{
|
||
|
CWeldableDoor *pWeldableDoor = dynamic_cast< CWeldableDoor * >( pTarget );
|
||
|
if ( pWeldableDoor )
|
||
|
{
|
||
|
pWeldableDoor->Unlock();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( !m_bLocked )
|
||
|
{
|
||
|
// Lock all the pieces of this door
|
||
|
m_bLocked = true;
|
||
|
|
||
|
CBaseEntity *pTarget = NULL;
|
||
|
if ( GetEntityName() != NULL_STRING )
|
||
|
{
|
||
|
while ( (pTarget = gEntList.FindEntityByName( pTarget, GetEntityName() )) != NULL )
|
||
|
{
|
||
|
if ( pTarget != this )
|
||
|
{
|
||
|
CWeldableDoor *pWeldableDoor = dynamic_cast< CWeldableDoor * >( pTarget );
|
||
|
if ( pWeldableDoor )
|
||
|
{
|
||
|
pWeldableDoor->Lock();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Update the beams
|
||
|
for ( int i = 0; i < m_aWeldPoints.Size(); i++ )
|
||
|
{
|
||
|
// First time we've updated?
|
||
|
if ( m_aWeldBeams.Size() <= i )
|
||
|
{
|
||
|
CBeam *pBeam = CBeam::BeamCreate( "sprites/physbeam.vmt", 4.0 );
|
||
|
pBeam->SetColor( 128, 128, 128 );
|
||
|
pBeam->SetBrightness( 128 );
|
||
|
pBeam->PointsInit( m_aWeldPoints[i]->GetStartPoint(), m_aWeldPoints[i]->GetEndPoint() );
|
||
|
m_aWeldBeams.AddToTail( pBeam );
|
||
|
}
|
||
|
if ( m_aCutBeams.Size() <= i )
|
||
|
{
|
||
|
CBeam *pBeam = CBeam::BeamCreate( "sprites/physbeam.vmt", 4.0 );
|
||
|
pBeam->SetColor( 255, 255, 255 );
|
||
|
pBeam->SetBrightness( 255 );
|
||
|
pBeam->PointsInit( m_aWeldPoints[i]->GetStartPoint(), m_aWeldPoints[i]->GetEndPoint() );
|
||
|
m_aCutBeams.AddToTail( pBeam );
|
||
|
}
|
||
|
|
||
|
// Figure out how far we've welded
|
||
|
Vector vecLine = ( m_aWeldPoints[i]->GetEndPoint() - m_aWeldPoints[i]->GetStartPoint());
|
||
|
float flLength = vecLine.Length();
|
||
|
VectorNormalize(vecLine);
|
||
|
vecLine = vecLine * (flLength * flWeldPercentage);
|
||
|
Vector vecWeldPoint = m_aWeldPoints[i]->GetStartPoint() + vecLine;
|
||
|
|
||
|
// Update the beams
|
||
|
m_aWeldBeams[i]->SetStartPos( m_aWeldPoints[i]->GetStartPoint() );
|
||
|
m_aWeldBeams[i]->SetEndPos( vecWeldPoint );
|
||
|
m_aWeldBeams[i]->RelinkBeam();
|
||
|
if ( flWeldPercentage <= m_flMaxWeldedPercentage )
|
||
|
{
|
||
|
// Get the cut point
|
||
|
VectorNormalize(vecLine);
|
||
|
vecLine = vecLine * (flLength * m_flMaxWeldedPercentage);
|
||
|
Vector vecCutPoint = m_aWeldPoints[i]->GetStartPoint() + vecLine;
|
||
|
|
||
|
m_aCutBeams[i]->SetEndPos( vecWeldPoint );
|
||
|
m_aCutBeams[i]->SetStartPos( vecCutPoint );
|
||
|
m_aCutBeams[i]->RelinkBeam();
|
||
|
}
|
||
|
|
||
|
// Some sparks
|
||
|
if ( random->RandomInt(0,2) == 0 )
|
||
|
{
|
||
|
g_pEffects->Sparks( vecWeldPoint );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Find a weld point to watch for this player
|
||
|
//-----------------------------------------------------------------------------
|
||
|
Vector CWeldableDoor::GetPlayerWeldPoint( void )
|
||
|
{
|
||
|
CBaseTFPlayer *pPlayer = (CBaseTFPlayer *)(CBaseEntity*)m_hWeldingPlayer;
|
||
|
Vector vecSrc = pPlayer->Weapon_ShootPosition( );
|
||
|
trace_t tr;
|
||
|
|
||
|
for ( int i = 0; i < m_aWeldPoints.Size(); i++ )
|
||
|
{
|
||
|
// Figure out where the weldpoint is
|
||
|
Vector vecLine = ( m_aWeldPoints[i]->GetEndPoint() - m_aWeldPoints[i]->GetStartPoint());
|
||
|
float flLength = vecLine.Length();
|
||
|
VectorNormalize(vecLine);
|
||
|
vecLine = vecLine * (flLength * m_flWeldedPercentage);
|
||
|
Vector vecWeldPoint = m_aWeldPoints[i]->GetStartPoint() + vecLine;
|
||
|
|
||
|
// Is the weld point visible to our player?
|
||
|
UTIL_TraceLine( vecSrc, vecWeldPoint, MASK_SOLID, pPlayer, TFCOLLISION_GROUP_WEAPON, &tr );
|
||
|
if ( tr.fraction == 1.0 )
|
||
|
return vecWeldPoint;
|
||
|
}
|
||
|
|
||
|
return vec3_origin;
|
||
|
}
|
||
|
|
||
|
|
||
|
//============================================================================================================
|
||
|
// WELD POINTS
|
||
|
//============================================================================================================
|
||
|
|
||
|
LINK_ENTITY_TO_CLASS( info_weldpoint, CWeldPoint );
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeldPoint::Spawn( void )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeldPoint::SetEndPoint( const Vector &vecEndPoint )
|
||
|
{
|
||
|
m_vecEndPoint = vecEndPoint;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
const Vector &CWeldPoint::GetStartPoint( void ) const
|
||
|
{
|
||
|
return GetLocalOrigin();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
const Vector &CWeldPoint::GetEndPoint( void ) const
|
||
|
{
|
||
|
return m_vecEndPoint;
|
||
|
}
|