source-engine/game/server/tf2/tf_func_weldable_door.cpp
FluorescentCIAAfricanAmerican 3bf9df6b27 1
2020-04-22 12:56:21 -04:00

400 lines
12 KiB
C++

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