mirror of
https://github.com/nillerusr/source-engine.git
synced 2024-12-23 14:46:53 +00:00
415 lines
12 KiB
C++
415 lines
12 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose: Teleport Station vehicle
|
|
//
|
|
//=============================================================================//
|
|
|
|
#include "cbase.h"
|
|
#include "tf_vehicle_teleport_station.h"
|
|
#include "engine/IEngineSound.h"
|
|
#include "VGuiScreen.h"
|
|
#include "ammodef.h"
|
|
#include "in_buttons.h"
|
|
#include "ndebugoverlay.h"
|
|
#include "IEffects.h"
|
|
#include "info_act.h"
|
|
#include "tf_obj_mcv_selection_panel.h"
|
|
#include "info_vehicle_bay.h"
|
|
|
|
#define TELEPORT_STATION_MINS Vector(-30, -50, -10)
|
|
#define TELEPORT_STATION_MAXS Vector( 30, 50, 55)
|
|
#define TELEPORT_STATION_MODEL "models/objects/vehicle_teleport_station.mdl"
|
|
#define TELEPORT_STATION_ZONE_HEIGHT 200
|
|
#define TELEPORT_STATION_THINK_CONTEXT "TeleportThink"
|
|
|
|
BEGIN_DATADESC( CVehicleTeleportStation )
|
|
|
|
DEFINE_THINKFUNC( PostTeleportThink ),
|
|
|
|
END_DATADESC()
|
|
|
|
IMPLEMENT_SERVERCLASS_ST( CVehicleTeleportStation, DT_VehicleTeleportStation )
|
|
END_SEND_TABLE()
|
|
|
|
LINK_ENTITY_TO_CLASS( vehicle_teleport_station, CVehicleTeleportStation );
|
|
PRECACHE_REGISTER( vehicle_teleport_station );
|
|
|
|
// CVars
|
|
ConVar vehicle_teleport_station_health( "vehicle_teleport_station_health","600", FCVAR_NONE, "Siege tower health" );
|
|
|
|
|
|
CUtlVector<CVehicleTeleportStation*> g_AllTeleportStations;
|
|
CUtlVector<CVehicleTeleportStation*> CVehicleTeleportStation::s_DeployedTeleportStations;
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
CVehicleTeleportStation::CVehicleTeleportStation()
|
|
{
|
|
g_AllTeleportStations.AddToTail( this );
|
|
|
|
//FIXME: we should be able to use clientside animation on this vehicle, but prediction is messing it
|
|
//up right now.
|
|
//UseClientSideAnimation();
|
|
}
|
|
|
|
|
|
CVehicleTeleportStation::~CVehicleTeleportStation()
|
|
{
|
|
g_AllTeleportStations.FindAndRemove( this );
|
|
s_DeployedTeleportStations.FindAndRemove( this );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CVehicleTeleportStation::Spawn()
|
|
{
|
|
SetModel( TELEPORT_STATION_MODEL );
|
|
|
|
// This size is used for placement only...
|
|
UTIL_SetSize( this, TELEPORT_STATION_MINS, TELEPORT_STATION_MAXS );
|
|
m_takedamage = DAMAGE_YES;
|
|
m_iHealth = vehicle_teleport_station_health.GetInt();
|
|
|
|
SetType( OBJ_VEHICLE_TELEPORT_STATION );
|
|
SetMaxPassengerCount( 4 );
|
|
SetBodygroup( 1, true );
|
|
|
|
BaseClass::Spawn();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CVehicleTeleportStation::Precache()
|
|
{
|
|
PrecacheModel( TELEPORT_STATION_MODEL );
|
|
|
|
PrecacheVGuiScreen( "screen_vehicle_bay" );
|
|
|
|
PrecacheModel( "sprites/redglow1.vmt" );
|
|
|
|
BaseClass::Precache();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CVehicleTeleportStation::UpdateOnRemove( void )
|
|
{
|
|
RemoveCornerSprites();
|
|
|
|
// Chain at end to mimic destructor unwind order
|
|
BaseClass::UpdateOnRemove();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Gets info about the control panels
|
|
//-----------------------------------------------------------------------------
|
|
void CVehicleTeleportStation::GetControlPanelInfo( int nPanelIndex, const char *&pPanelName )
|
|
{
|
|
pPanelName = "screen_vehicle_bay";
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CVehicleTeleportStation::GetControlPanelClassName( int nPanelIndex, const char *&pPanelName )
|
|
{
|
|
pPanelName = "vgui_screen_vehicle_bay";
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Screens aren't active until deployed
|
|
//-----------------------------------------------------------------------------
|
|
void CVehicleTeleportStation::FinishedBuilding( void )
|
|
{
|
|
BaseClass::FinishedBuilding();
|
|
|
|
SetControlPanelsActive( false );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Here's where we deal with weapons, ladders, etc.
|
|
//-----------------------------------------------------------------------------
|
|
void CVehicleTeleportStation::OnItemPostFrame( CBaseTFPlayer *pDriver )
|
|
{
|
|
// I can't do anything if I'm not active
|
|
if ( !ShouldBeActive() )
|
|
return;
|
|
|
|
if ( GetPassengerRole( pDriver ) != VEHICLE_ROLE_DRIVER )
|
|
return;
|
|
|
|
if ( !IsDeployed() && ( pDriver->m_afButtonPressed & IN_ATTACK ) )
|
|
{
|
|
if ( ValidDeployPosition() )
|
|
{
|
|
Deploy();
|
|
}
|
|
}
|
|
else if ( IsDeployed() && ( pDriver->m_afButtonPressed & IN_ATTACK ) )
|
|
{
|
|
UnDeploy();
|
|
|
|
SetControlPanelsActive( false );
|
|
SetBodygroup( 1, true );
|
|
RemoveCornerSprites();
|
|
SetContextThink( NULL, 0, TELEPORT_STATION_THINK_CONTEXT );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Finished our deploy
|
|
//-----------------------------------------------------------------------------
|
|
void CVehicleTeleportStation::OnFinishedDeploy( void )
|
|
{
|
|
BaseClass::OnFinishedDeploy();
|
|
|
|
ValidDeployPosition();
|
|
SetBodygroup( 1, false );
|
|
|
|
// Find the teleport in the mothership
|
|
CFuncMassTeleport *pTeleporter = NULL;
|
|
while ( (pTeleporter = (CFuncMassTeleport*)gEntList.FindEntityByClassname( pTeleporter, "func_mass_teleport" )) != NULL )
|
|
{
|
|
if ( pTeleporter->IsMCVTeleport() )
|
|
{
|
|
m_hTeleportExit = pTeleporter;
|
|
m_hTeleportExit->AddMCV( this );
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Put some flares down to mark the teleport zone
|
|
Vector vecOrigin;
|
|
QAngle vecAngles;
|
|
for ( int i = 0; i < 4; i++ )
|
|
{
|
|
char buf[64];
|
|
Q_snprintf( buf, sizeof( buf ), "teleport_corner%d", i+1 );
|
|
if ( GetAttachment( buf, vecOrigin, vecAngles ) )
|
|
{
|
|
CheckBuildPoint( vecOrigin + Vector(0,0,64), Vector(0,0,128), &vecOrigin );
|
|
m_hTeleportCornerSprites[i] = CSprite::SpriteCreate( "sprites/redglow1.vmt", vecOrigin, false );
|
|
m_hTeleportCornerSprites[i]->SetTransparency( kRenderGlow, 255, 255, 255, 255, kRenderFxNoDissipation );
|
|
m_hTeleportCornerSprites[i]->SetScale( 0.1 );
|
|
}
|
|
}
|
|
// Get the ray point
|
|
if ( GetAttachment( "muzzle", vecOrigin, vecAngles ) )
|
|
{
|
|
m_hTeleportCornerSprites[4] = CSprite::SpriteCreate( "sprites/redglow1.vmt", vecOrigin, false );
|
|
m_hTeleportCornerSprites[4]->SetTransparency( kRenderGlow, 255, 255, 255, 255, kRenderFxNoDissipation );
|
|
m_hTeleportCornerSprites[4]->SetScale( 0.1 );
|
|
}
|
|
|
|
SetContextThink( PostTeleportThink, gpGlobals->curtime + 0.1, TELEPORT_STATION_THINK_CONTEXT );
|
|
|
|
// Add ourselves to the list of deployed MCVs.
|
|
s_DeployedTeleportStations.AddToTail( this );
|
|
|
|
// Set our vehicle bay screen's buildpoint
|
|
for ( i = m_hScreens.Count(); --i >= 0; )
|
|
{
|
|
if (m_hScreens[i].Get())
|
|
{
|
|
CVGuiScreenVehicleBay *pScreen = dynamic_cast<CVGuiScreenVehicleBay*>( m_hScreens[0].Get() );
|
|
if ( pScreen )
|
|
{
|
|
Vector vecOrigin;
|
|
QAngle vecAngles;
|
|
if ( GetAttachment( "vehiclebay", vecOrigin, vecAngles ) )
|
|
{
|
|
pScreen->SetBuildPoint( vecOrigin, vecAngles );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SetControlPanelsActive( true );
|
|
|
|
SignalChangeInMCVSelectionPanels();
|
|
}
|
|
|
|
|
|
void CVehicleTeleportStation::OnFinishedUnDeploy( void )
|
|
{
|
|
BaseClass::OnFinishedUnDeploy();
|
|
|
|
s_DeployedTeleportStations.FindAndRemove( this );
|
|
SignalChangeInMCVSelectionPanels();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CVehicleTeleportStation::RemoveCornerSprites( void )
|
|
{
|
|
// Remove all the corner sprites
|
|
for ( int i = 0; i < 5; i++ )
|
|
{
|
|
if ( m_hTeleportCornerSprites[i] )
|
|
{
|
|
UTIL_Remove( m_hTeleportCornerSprites[i] );
|
|
}
|
|
}
|
|
|
|
// Tell the exit we're done
|
|
if ( m_hTeleportExit )
|
|
{
|
|
m_hTeleportExit->RemoveMCV( this );
|
|
m_hTeleportExit = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
int CVehicleTeleportStation::GetNumDeployedTeleportStations()
|
|
{
|
|
return s_DeployedTeleportStations.Count();
|
|
}
|
|
|
|
|
|
CVehicleTeleportStation* CVehicleTeleportStation::GetDeployedTeleportStation( int i )
|
|
{
|
|
return s_DeployedTeleportStations[i];
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Return true if the truck's in a valid position
|
|
//-----------------------------------------------------------------------------
|
|
bool CVehicleTeleportStation::ValidDeployPosition( void )
|
|
{
|
|
// Setup for teleporting
|
|
QAngle vecAngles;
|
|
if ( !GetAttachment( "teleport_corner1", m_vecTeleporterMins, vecAngles ) || !GetAttachment( "teleport_corner4", m_vecTeleporterMaxs, vecAngles ) )
|
|
return false;
|
|
|
|
m_vecTeleporterMaxs.z += TELEPORT_STATION_ZONE_HEIGHT;
|
|
|
|
// Make sure we've got the right mins & maxs
|
|
for ( int i = 0; i < 3; i++ )
|
|
{
|
|
if ( m_vecTeleporterMaxs[i] < m_vecTeleporterMins[i] )
|
|
{
|
|
float flVal = m_vecTeleporterMaxs[i];
|
|
m_vecTeleporterMaxs[i] = m_vecTeleporterMins[i];
|
|
m_vecTeleporterMins[i] = flVal;
|
|
}
|
|
}
|
|
|
|
Vector vecDelta = (m_vecTeleporterMaxs - m_vecTeleporterMins) * 0.5;
|
|
Vector vecEnd = (m_vecTeleporterMaxs + m_vecTeleporterMins) * 0.5;
|
|
Vector vecSrc = vecEnd + Vector(0,0,TELEPORT_STATION_ZONE_HEIGHT * 0.5);
|
|
|
|
// Make sure it's clear
|
|
// Take the hull, start it high, and try and trace down
|
|
trace_t tr;
|
|
UTIL_TraceHull( vecSrc, vecEnd, -vecDelta, vecDelta, MASK_SOLID, this, COLLISION_GROUP_PLAYER_MOVEMENT, &tr );
|
|
|
|
//NDebugOverlay::Box( m_vecTeleporterMins, Vector(-2,-2,-2), Vector(2,2,2), 0,255,0,8, 0.1 );
|
|
//NDebugOverlay::Box( m_vecTeleporterMaxs, Vector(-2,-2,-2), Vector(2,2,2), 0,255,0,8, 0.1 );
|
|
//NDebugOverlay::Box( vecSrc, -vecDelta, vecDelta, 255,0,0,8, 0.1 );
|
|
//NDebugOverlay::Box( vecEnd, -vecDelta, vecDelta, 0,0,255,8, 0.1 );
|
|
//NDebugOverlay::Line( m_vecTeleporterMins, m_vecTeleporterMaxs, 255,255,255, 1, 0.1 );
|
|
|
|
// Make sure it's clear
|
|
if ( tr.startsolid )
|
|
return false;
|
|
|
|
// Get a list of nearby entities
|
|
CBaseEntity *pListOfNearbyEntities[100];
|
|
int iNumberOfNearbyEntities = UTIL_EntitiesInBox( pListOfNearbyEntities, 100, m_vecTeleporterMins, m_vecTeleporterMaxs, MASK_ALL );
|
|
for ( i = 0; i < iNumberOfNearbyEntities; i++ )
|
|
{
|
|
CBaseEntity *pEntity = pListOfNearbyEntities[i];
|
|
if ( pEntity->IsSolid( ) )
|
|
{
|
|
if ( pEntity == this )
|
|
continue;
|
|
if ( pEntity->GetCollisionGroup() == TFCOLLISION_GROUP_SHIELD )
|
|
continue;
|
|
if ( pEntity->IsPlayer() )
|
|
continue;
|
|
|
|
//NDebugOverlay::EntityBounds( pEntity, 0,255,0,8, 0.1 );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
m_vecTeleporterCenter = vecEnd;
|
|
m_vecTeleporterCenter.z = m_vecTeleporterMins.z;
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CVehicleTeleportStation::DoTeleport( void )
|
|
{
|
|
ResetDeteriorationTime();
|
|
|
|
if ( m_hTeleportExit )
|
|
{
|
|
// Teleport all players attached to me that are within my bbox.
|
|
EHANDLE hMCV;
|
|
hMCV = this;
|
|
Vector vecAbsMins, vecAbsMaxs;
|
|
m_hTeleportExit->CollisionProp()->WorldSpaceAABB( &vecAbsMins, &vecAbsMaxs );
|
|
m_hTeleportExit->DoTeleport( GetTFTeam(), vecAbsMins, vecAbsMaxs, m_vecTeleporterCenter, true, true, hMCV );
|
|
}
|
|
|
|
// Shrink the corner sprites
|
|
for ( int i = 0; i < 5; i++ )
|
|
{
|
|
if ( m_hTeleportCornerSprites[i] )
|
|
{
|
|
m_hTeleportCornerSprites[i]->SetScale( 0.1 );
|
|
}
|
|
}
|
|
|
|
SetContextThink( PostTeleportThink, gpGlobals->curtime + 0.1, TELEPORT_STATION_THINK_CONTEXT );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CVehicleTeleportStation::PostTeleportThink( void )
|
|
{
|
|
float flTime = 10.0;
|
|
if ( g_hCurrentAct )
|
|
{
|
|
flTime = g_hCurrentAct->GetMCVTimer();
|
|
}
|
|
|
|
// Start the corner sprites up
|
|
for ( int i = 0; i < 4; i++ )
|
|
{
|
|
if ( m_hTeleportCornerSprites[i] )
|
|
{
|
|
m_hTeleportCornerSprites[i]->SetScale( 0.75, flTime );
|
|
}
|
|
}
|
|
m_hTeleportCornerSprites[4]->SetScale( 2, flTime );
|
|
}
|
|
|
|
|
|
// Returns INVALID_MCV_ID if there are no deployed MCVs.
|
|
CVehicleTeleportStation* CVehicleTeleportStation::GetFirstDeployedMCV( int iTeam )
|
|
{
|
|
for ( int i=0; i < s_DeployedTeleportStations.Count(); i++ )
|
|
{
|
|
CVehicleTeleportStation *pStation = s_DeployedTeleportStations[i];
|
|
|
|
if ( pStation->GetTeamNumber() == iTeam )
|
|
return pStation;
|
|
}
|
|
return NULL;
|
|
}
|
|
|