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