diff options
Diffstat (limited to 'game/server/tf2/tf_vehicle_teleport_station.cpp')
| -rw-r--r-- | game/server/tf2/tf_vehicle_teleport_station.cpp | 414 |
1 files changed, 414 insertions, 0 deletions
diff --git a/game/server/tf2/tf_vehicle_teleport_station.cpp b/game/server/tf2/tf_vehicle_teleport_station.cpp new file mode 100644 index 0000000..2ecdd70 --- /dev/null +++ b/game/server/tf2/tf_vehicle_teleport_station.cpp @@ -0,0 +1,414 @@ +//========= 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; +} + |