sqwarmed/sdk_src/game/shared/swarm/asw_player_shared.cpp

1171 lines
31 KiB
C++

#include "cbase.h"
#ifdef CLIENT_DLL
#include "c_asw_player.h"
#include "c_asw_marine.h"
#include "c_asw_game_resource.h"
#include "c_asw_marine_resource.h"
#include "asw_marine_command.h"
#include "asw_imarinegamemovement.h"
#include "asw_marine_gamemovement.h"
#include "engine/IEngineSound.h"
#include "c_asw_pickup.h"
#include "c_asw_pickup_weapon.h"
#include "c_asw_use_area.h"
#include "c_asw_button_area.h"
#include "c_asw_computer_area.h"
#include "c_asw_sentry_base.h"
#include "iinput.h"
#include "asw_input.h"
#include "iclientvehicle.h"
#include "c_asw_jeep_clientside.h"
#include "iasw_client_vehicle.h"
#include "c_asw_weapon.h"
#include "c_asw_game_resource.h"
#include "c_asw_hack.h"
#include "iasw_client_usable_entity.h"
#include "asw_vgui_info_message.h"
#include "prediction.h"
#include "igameevents.h"
#include "c_asw_ammo_drop.h"
#define CASW_Button_Area C_ASW_Button_Area
#define CASW_Computer_Area C_ASW_Computer_Area
#define CASW_Use_Area C_ASW_Use_Area
#define CASW_Pickup C_ASW_Pickup
#define CASW_Ammo_Drop C_ASW_Ammo_Drop
#define CASW_Marine C_ASW_Marine
#define CASW_Marine_Resource C_ASW_Marine_Resource
#define CASW_Sentry_Base C_ASW_Sentry_Base
#define CASW_Weapon C_ASW_Weapon
#define CASW_Hack C_ASW_Hack
#else
#include "player.h"
#include "asw_player.h"
#include "asw_marine.h"
#include "asw_marine_resource.h"
#include "usercmd.h"
#include "igamemovement.h"
#include "mathlib/mathlib.h"
#include "client.h"
#include "player_command.h"
#include "asw_marine_command.h"
#include "asw_imarinegamemovement.h"
#include "asw_marine_gamemovement.h"
#include "movehelper_server.h"
#include "iservervehicle.h"
#include "ilagcompensationmanager.h"
#include "tier0/vprof.h"
#include "asw_pickup.h"
#include "asw_use_area.h"
#include "asw_button_area.h"
#include "asw_computer_area.h"
#include "asw_sentry_base.h"
#include "iservervehicle.h"
#include "iasw_vehicle.h"
#include "asw_weapon.h"
#include "asw_hack.h"
#include "iasw_server_usable_entity.h"
#include "asw_lag_compensation.h"
#include "asw_ammo_drop.h"
extern ConVar asw_move_marine;
#endif
#include "asw_gamerules.h"
#include "asw_remote_turret_shared.h"
#include "asw_shareddefs.h"
#include "asw_usableobjectsenumerator.h"
#include "in_buttons.h"
#include "asw_weapon_parse.h"
#include "collisionutils.h"
#include "particle_parse.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern IGameMovement *g_pGameMovement;
extern IMarineGameMovement *g_pMarineGameMovement;
extern CMoveData *g_pMoveData; // This is a global because it is subclassed by each game.
extern ConVar sv_noclipduringpause;
ConVar asw_allow_detach("asw_allow_detach", "0", FCVAR_REPLICATED | FCVAR_CHEAT, "Allow the camera to detach from the marine.");
ConVar asw_DebugAutoAim("asw_DebugAutoAim", "0", FCVAR_REPLICATED | FCVAR_CHEAT);
ConVar asw_marine_nearby_angle("asw_marine_nearby_angle", "-75", FCVAR_REPLICATED | FCVAR_CHEAT);
ConVar asw_rts_controls("asw_rts_controls", "0", FCVAR_REPLICATED | FCVAR_CHEAT);
ConVar asw_controls("asw_controls", "1", FCVAR_REPLICATED | FCVAR_CHEAT, "Disable to get normal FPS controls (affects all players on the server)");
ConVar asw_hl2_camera("asw_hl2_camera", "0", FCVAR_REPLICATED | FCVAR_DONTRECORD | FCVAR_CHEAT);
#ifdef CLIENT_DLL
extern ConVar asw_vehicle_cam_height;
extern ConVar asw_vehicle_cam_pitch;
extern ConVar asw_vehicle_cam_dist;
extern ConVar asw_cam_marine_shift_z_death;
#endif
extern void DiffPrint( bool bServer, int nCommandNumber, char const *fmt, ... );
void CASW_Player::DriveMarineMovement( CUserCmd *ucmd, IMoveHelper *moveHelper )
{
CASW_Marine *pMarine = GetMarine();
if ( pMarine )
{
MoveHelper()->SetHost( pMarine );
}
// process turret movement
if ( pMarine && pMarine->IsControllingTurret())
{
CASW_Remote_Turret* pTurret = pMarine->GetRemoteTurret();
if (pTurret)
{
pTurret->SetupMove( this, ucmd, moveHelper, g_pMoveData );
pTurret->ProcessMovement( this, g_pMoveData );
}
pMarine->PostThink();
return;
}
// process vehicle movement
#ifdef GAME_DLL
if ( pMarine && pMarine->IsDriving() && gpGlobals->maxClients == 1)
{
IASW_Vehicle* pVehicle = pMarine->GetASWVehicle();
if (pVehicle)
{
pVehicle->SetupMove( this, ucmd, moveHelper, g_pMoveData );
pVehicle->ProcessMovement( this, g_pMoveData );
}
}
// store light level for stats tracking
//if ( pMarine )
//{
//pMarine->m_iLightLevel = ucmd->light_level;
//}
#else
if ( pMarine && gpGlobals->maxClients > 1)
{
IASW_Client_Vehicle* pVehicle = pMarine->GetClientsideVehicle();
if ( pMarine->IsDriving())
{
if (pVehicle)
{
pVehicle->SetupMove( this, ucmd, moveHelper, g_pMoveData );
pVehicle->ProcessMovement( this, g_pMoveData );
}
else if ( pMarine->GetASWVehicle() && pMarine->GetASWVehicle()->GetEntity() &&
pMarine->GetASWVehicle()->ASWGetDriver() == pMarine )
{
// need to create a clientside vehicle for us to drive
CBaseEntity* pEnt = pMarine->GetASWVehicle()->GetEntity();
C_ASW_PropJeep_Clientside* pJeep = C_ASW_PropJeep_Clientside::CreateNew(false);
pJeep->SetAbsOrigin(pEnt->GetAbsOrigin());
pJeep->SetAbsAngles(pEnt->GetAbsAngles());
// todo: set poseparameters too?
pJeep->Initialize();
pMarine->SetClientsideVehicle(pJeep);
// hide the dummy for this client only
pMarine->GetASWVehicle()->GetEntity()->UpdateVisibility();
}
}
else
{
if ( pMarine->GetClientsideVehicle() )
{
pMarine->GetClientsideVehicle()->ASWStopEngine(); // destroys it
pMarine->SetClientsideVehicle(NULL);
// the dummy will show itself in its next clientthink...
}
}
}
#endif
#ifdef GAME_DLL
if ( asw_move_marine.GetBool() )
{
#endif
if ( pMarine && !pMarine->IsInVehicle() && ASWGameResource() )
{
// don't apply commands meant for another marine
if ( pMarine->GetMarineResource() && ASWGameResource()->GetMarineResourceIndex( pMarine->GetMarineResource() ) == ucmd->weaponsubtype)
{
// check if we should be stopped
if (gpGlobals->curtime < pMarine->GetStopTime() || pMarine->m_bPreventMovement
#ifdef CLIENT_DLL
|| CASW_VGUI_Info_Message::HasInfoMessageOpen()
#endif
)
{
ucmd->forwardmove = 0;
ucmd->sidemove = 0;
ucmd->buttons &= ~IN_JUMP;
// no firing when picking up stuff - does this do anything here?
if (gpGlobals->curtime < pMarine->GetStopTime())
{
ucmd->buttons &= ~IN_ATTACK;
ucmd->buttons &= ~IN_ATTACK2;
}
//ucmd->buttons |= IN_ASW_STOP;
}
m_hMarine->SetMoveType( MOVETYPE_WALK );
MarineMove()->SetupMarineMove( this, m_hMarine.Get(), ucmd, moveHelper, g_pMoveData);
g_pMarineGameMovement->ProcessMovement(this, m_hMarine.Get(), g_pMoveData);
MarineMove()->FinishMarineMove( this, m_hMarine.Get(), ucmd, g_pMoveData );
moveHelper->ProcessImpacts();
// Call this from within predicted code on both client & server
pMarine->PostThink();
#ifdef GAME_DLL
pMarine->PostThinkVPhysics(g_pMoveData);
pMarine->UpdateVPhysicsAfterMove();
#endif
}
if ( pMarine->m_hCurrentHack.Get() )
{
pMarine->m_hCurrentHack->ASWPostThink( this, pMarine, ucmd, gpGlobals->frametime );
}
// move the player into the same position as the marine
//SetAbsOrigin( g_pMoveData->m_vecAbsOrigin );
//SetAbsVelocity( g_pMoveData->m_vecVelocity );
//SetLocalAngles( g_pMoveData->m_vecAngles );
//m_pMarine->m_nSimulationTick = gpGlobals->tickcount; // stop the entity doing any subsequence physicssimulate
}
#ifdef GAME_DLL
}
#endif
MoveHelper()->SetHost( this );
}
void CASW_Player::ItemPostFrame()
{
VPROF( "CASW_Player::ItemPostFrame" );
// Put viewmodels into basically correct place based on new polayer origin
CalcViewModelView( EyePosition(), EyeAngles() );
#if !defined( CLIENT_DLL )
// check if the player is using something
if ( m_hUseEntity != NULL )
{
Assert( !IsInAVehicle() );
ImpulseCommands();// this will call playerUse
return;
}
#endif
CASW_Weapon* pWeapon = NULL;
CASW_Marine *pMarine = GetMarine();
float next_attack = m_flNextAttack;
if ( pMarine )
{
pWeapon = GetMarine()->GetActiveASWWeapon();
next_attack = GetMarine()->GetNextAttack();
}
else
{
pWeapon = dynamic_cast<CASW_Weapon*>(GetActiveWeapon());
}
// CASW_Lag_Compensation NOTE: From this point on, weapons can turn on lag compensation.
// This function must call FinishLagCompensation before returning.
#ifdef GAME_DLL
CASW_Lag_Compensation::AllowLagCompensation( this );
#endif
if ( gpGlobals->curtime < next_attack )
{
if ( pWeapon )
{
pWeapon->ItemBusyFrame();
}
}
else if (pWeapon)
{
#ifdef CLIENT_DLL
pWeapon->ClientPostFrame();
if ( pWeapon->IsPredicted() )
pWeapon->ItemPostFrame();
#else
pWeapon->ItemPostFrame();
#endif
}
// check if offhand weapon needs postframe
CASW_Weapon *pExtra = GetMarine() ? GetMarine()->GetASWWeapon(2) : NULL;
if (pExtra && pExtra != pWeapon && pExtra->WantsOffhandPostFrame() )
{
pExtra->ItemPostFrame();
}
// check for offhand activation
if ( pExtra )
{
if ( pExtra->GetWeaponInfo() && ( m_afButtonPressed & IN_GRENADE1 ) )
{
if ( pExtra->GetWeaponInfo()->m_bOffhandActivate )
{
if ( pExtra->OffhandActivate() )
{
IGameEvent * event = gameeventmanager->CreateEvent( "weapon_offhanded" );
if ( event )
{
event->SetInt( "userid", GetUserID() );
gameeventmanager->FireEvent( event );
}
}
}
else if ( pExtra->GetWeaponInfo()->m_bOffhandSwitch )
{
#ifdef CLIENT_DLL
::input->MakeWeaponSelection( pExtra );
#else
if ( gpGlobals->maxClients <= 1 )
{
engine->ClientCommand( edict(), "ASW_ActivateExtra" );
}
#endif
}
}
}
#if !defined( CLIENT_DLL )
ImpulseCommands();
#else
m_nImpulse = 0;
#endif
#ifdef GAME_DLL
CASW_Lag_Compensation::FinishLagCompensation(); // undo lag compensation if we need to
#endif
}
// the player's eyes go above the marine he's spectating/controlling
Vector CASW_Player::EyePosition( )
{
// revert to hl2 camera
#ifdef CLIENT_DLL
if (asw_hl2_camera.GetBool() && engine->IsPlayingDemo())
#else
if (asw_hl2_camera.GetBool())
#endif
{
return BaseClass::EyePosition();
}
CASW_Marine *pMarine = GetSpectatingMarine();
bool bSpectating = true;
if ( !pMarine )
{
pMarine = GetMarine();
bSpectating = false;
}
if ( pMarine && pMarine->GetHealth() > 0 )
{
m_vecLastMarineOrigin = pMarine->EyePosition();
}
if (!pMarine && asw_rts_controls.GetBool())
{
return GetAbsOrigin();
}
if ( m_vecLastMarineOrigin != vec3_origin )
{
#ifdef CLIENT_DLL
if ( asw_allow_detach.GetBool() )
{
return BaseClass::EyePosition();
}
bool bIsThirdPerson = ( ::input->CAM_IsThirdPerson() != 0 );
Vector org = vec3_origin;
QAngle ang;
if ( pMarine && pMarine->IsInVehicle() )
{
ang[PITCH] = asw_vehicle_cam_pitch.GetFloat();
ang[YAW] = pMarine->EyeAngles()[YAW] - 90;
ang[ROLL] = 0;
AngleVectors( ang, &org );
//if (input->CAM_IsThirdPerson())
//org *= -asw_vehicle_cam_dist.GetFloat();
org += m_vecLastMarineOrigin;
org.z += asw_vehicle_cam_height.GetFloat();
}
else if ( pMarine && pMarine->IsControllingTurret() )
{
if ( bSpectating )
{
ang[PITCH] = ASWInput()->ASW_GetCameraPitch();
ang[YAW] = ASWInput()->ASW_GetCameraYaw();
ang[ROLL] = 0;
AngleVectors(ang, &org);
if ( bIsThirdPerson )
{
org *= -::ASWInput()->ASW_GetCameraDist();
}
org += pMarine->GetRemoteTurret()->GetRenderOrigin();
}
else
{
org = pMarine->GetRemoteTurret()->GetTurretCamPosition();
}
}
else
{
float fDeathCamInterp = ( ASWGameRules() ? ASWGameRules()->GetMarineDeathCamInterp() : 0.0f );
if ( fDeathCamInterp <= 0.0f )
{
// Not doing the death cam!
Vector vCamOffset;
ang[PITCH] = ASWInput()->ASW_GetCameraPitch();
ang[YAW] = ASWInput()->ASW_GetCameraYaw();
ang[ROLL] = 0;
AngleVectors( ang, &vCamOffset );
if ( bIsThirdPerson )
{
vCamOffset *= -ASWInput()->ASW_GetCameraDist();
}
org = m_vecLastMarineOrigin + vCamOffset;
}
else
{
// Do the death cam!
Vector vCamOffset;
float fOffsetScale = 1.0f;
Vector vDeathPos = ASWGameRules()->m_vMarineDeathPos;
if ( ASWGameRules()->m_hMarineDeathRagdoll.Get() )
{
vDeathPos = ASWGameRules()->m_hMarineDeathRagdoll->WorldSpaceCenter();
}
vDeathPos.z += 50.0f;
// Prevent final death cam pos from clipping through walls
const float flMaxDeathCamInterp = 1.0f;
float fBaseYaw = ASWInput()->ASW_GetCameraYaw( &flMaxDeathCamInterp );
ang[PITCH] = ASWInput()->ASW_GetCameraPitch( &flMaxDeathCamInterp );
ang[ROLL] = 0;
float fMaxDeathCamDist = -ASWInput()->ASW_GetCameraDist( &flMaxDeathCamInterp );
trace_t tr;
tr.fraction = -1.0f;
float fBestYawOffset = 0.0f;
// Forward look at a bunch of angles to see if we can find a better one
const int nNumAngleTests = 12;
for ( int nAngleTest = 0; nAngleTest < nNumAngleTests; ++nAngleTest )
{
float fYawAngleOffset = nAngleTest * ( 360.0f / nNumAngleTests );
ang[ YAW ] = fBaseYaw + fYawAngleOffset;
AngleVectors( ang, &vCamOffset );
if ( bIsThirdPerson )
{
vCamOffset *= fMaxDeathCamDist;
}
vCamOffset.z += asw_cam_marine_shift_z_death.GetFloat();
// See if the new angle is clipping
trace_t trTemp;
UTIL_TraceLine( vDeathPos, vDeathPos + vCamOffset, MASK_OPAQUE, NULL, COLLISION_GROUP_DEBRIS, &trTemp );
if ( !trTemp.DidHit() )
{
// Not cliping at all
tr = trTemp;
fBestYawOffset = fYawAngleOffset;
break;
}
else if ( tr.fraction + 0.15f < trTemp.fraction )
{
// It's quite a bit better than what we're currently using
tr = trTemp;
fBestYawOffset = fYawAngleOffset;
}
}
ASWGameRules()->m_fDeathCamYawAngleOffset += fBestYawOffset;
fOffsetScale = tr.fraction;
// Blend the death cam position with the regular game view
ang[PITCH] = ASWInput()->ASW_GetCameraPitch( &fDeathCamInterp );
ang[YAW] = ASWInput()->ASW_GetCameraYaw( &fDeathCamInterp );
ang[ROLL] = 0;
AngleVectors( ang, &vCamOffset );
if ( bIsThirdPerson )
{
vCamOffset *= -ASWInput()->ASW_GetCameraDist( &fDeathCamInterp );
}
vCamOffset.z += fDeathCamInterp * asw_cam_marine_shift_z_death.GetFloat();
org = ( 1.0f - fDeathCamInterp ) * m_vecLastMarineOrigin + fDeathCamInterp * vDeathPos;
org += vCamOffset * fOffsetScale;
}
}
return org;
#else
return m_vecLastMarineOrigin + Vector(0,0,405); // todo: make this take into account mouse location, based on the pitch coming in from player commands
#endif
}
return BaseClass::EyePosition();
}
// tries to find up to 3 nearby usable items and fills in our array (the array is inspected by the HUD to present use icons)
void CASW_Player::FindUseEntities()
{
CBaseEntity *pOldUseEntity = NULL;
pOldUseEntity = m_hUseEntities[ 0 ].Get();
// Clear out all the old use ents
m_iUseEntities = 0;
for ( int i = 0; i < ASW_PLAYER_MAX_USE_ENTS; ++i )
{
m_hUseEntities[ i ] = NULL;
}
CASW_Marine* pMarine = GetMarine();
if (!pMarine)
{
return;
}
// if we're in a vehicle, only interact with the vehicle (to get out)
if ( pMarine->IsInVehicle() )
{
if ( pMarine->GetASWVehicle() && pMarine->GetASWVehicle()->GetEntity() )
{
m_hUseEntities[ 0 ] = pMarine->GetASWVehicle()->GetEntity();
m_iUseEntities = 1;
}
return;
}
CASW_UsableObjectsEnumerator items( ASW_MARINE_USE_RADIUS, this );
#ifdef CLIENT_DLL
partition->EnumerateElementsInSphere( PARTITION_ALL_CLIENT_EDICTS, pMarine->GetAbsOrigin(), ASW_MARINE_USE_RADIUS, false, &items );
#else
partition->EnumerateElementsInSphere( ASW_PARTITION_ALL_SERVER_EDICTS , pMarine->GetAbsOrigin(), ASW_MARINE_USE_RADIUS, false, &items );
#endif
int c = items.GetObjectCount();
#ifndef CLIENT_DLL
//Msg("[S] Enumerator returned %d items.\n", c);
#endif
if ( c <= 0 )
{
return;
}
CBaseEntity *(pUseEntities[ 32 ]);
for ( int i = 0; i < c && i < 32; i++ )
{
#ifdef CLIENT_DLL
IASW_Client_Usable_Entity *pEnt = dynamic_cast<IASW_Client_Usable_Entity*>(items.GetObject(i));
#else
IASW_Server_Usable_Entity *pEnt = dynamic_cast<IASW_Server_Usable_Entity*>(items.GetObject(i));
#endif
if ( pEnt )
{
if ( !pMarine->m_hUsingEntity.Get() || pMarine->m_hUsingEntity.Get() == items.GetObject( i ) ) // if we're in the middle of using an entity, only allow interaction with that entity
{
pUseEntities[ m_iUseEntities ] = items.GetObject( i );
m_iUseEntities++;
}
}
}
// Store off use priorities first because sometimes it takes expensive traces to decide
int nUsePriorities[ 32 ];
for ( int i = 0; i < m_iUseEntities; ++i )
{
nUsePriorities[ i ] = GetUsePriority( pUseEntities[ i ] );
}
// sort the use entities
for ( int i = 0; i < m_iUseEntities - 1; ++i )
{
for ( int j = 0; j < m_iUseEntities - i - 1; ++j )
{
SortUsePair( &pUseEntities[ j ], &pUseEntities[ j + 1 ], &nUsePriorities[ j ], &nUsePriorities[ j + 1 ] );
}
}
m_iUseEntities = MIN( 3, m_iUseEntities );
for ( int i = 0; i < m_iUseEntities; ++i )
{
m_hUseEntities[ i ] = pUseEntities[ i ];
}
#ifdef CLIENT_DLL
C_ASW_Pickup_Weapon *pWeapon = dynamic_cast<C_ASW_Pickup_Weapon*>( m_hUseEntities[ 0 ].Get() );
if ( pWeapon && pWeapon != pOldUseEntity )
{
IGameEvent * event = gameeventmanager->CreateEvent( "pickup_selected" );
if ( event )
{
event->SetInt( "entindex", pWeapon->entindex() );
event->SetString( "classname", pWeapon->GetWeaponClass() );
gameeventmanager->FireEventClientSide( event );
}
}
else
{
C_ASW_Sentry_Base *pSentry = dynamic_cast<C_ASW_Sentry_Base*>( m_hUseEntities[ 0 ].Get() );
if ( pSentry && pSentry != pOldUseEntity && pSentry->IsAssembled() )
{
IGameEvent * event = gameeventmanager->CreateEvent( "sentry_selected" );
if ( event )
{
event->SetInt( "entindex", pSentry->entindex() );
gameeventmanager->FireEventClientSide( event );
}
}
}
#endif
}
// finds the priority of the pair of use entities at the specified index
// and swaps them so the highest priority one is first
void CASW_Player::SortUsePair( CBaseEntity **pEnt1, CBaseEntity **pEnt2, int *pnFirstPriority, int *pnSecondPriority )
{
if ( !pEnt1 || !pEnt2 || !*pEnt1 || !*pEnt2 || !pnFirstPriority || !pnSecondPriority )
return;
bool bSwap = false;
if ( *pnFirstPriority == *pnSecondPriority ) // if items are the same type, put the closest first
{
CASW_Marine* pMarine = GetMarine();
if ( pMarine != NULL )
{
float fFirstDist = pMarine->GetAbsOrigin().DistToSqr( ( *pEnt1 )->WorldSpaceCenter() );
float fSecondDist = pMarine->GetAbsOrigin().DistToSqr( ( *pEnt2 )->WorldSpaceCenter() );
if ( fSecondDist < fFirstDist)
{
bSwap = true;
}
}
}
else if ( *pnSecondPriority > *pnFirstPriority )
{
bSwap = true;
}
if ( bSwap )
{
CBaseEntity *pTempEnt = *pEnt1;
*pEnt1 = *pEnt2;
*pEnt2 = pTempEnt;
int nTemp = *pnFirstPriority;
*pnFirstPriority = *pnSecondPriority;
*pnSecondPriority = nTemp;
}
}
// returns the priority of a usable entity
int CASW_Player::GetUsePriority( CBaseEntity* pEnt )
{
if ( !pEnt )
return 0;
if ( !pEnt->IsEffectActive( EF_NODRAW ) )
{
Vector vTracePos =
#ifdef GAME_DLL
GetCrosshairTracePos();
#else
ASWInput()->GetCrosshairTracePos();
#endif
CCollisionProperty *pMyProp = pEnt->CollisionProp();
Ray_t ray;
ray.Init( vTracePos + Vector( 0.0f, 0.0f, -10.0f ), vTracePos + Vector( 0.0f, 0.0f, 10.0f ) );
#ifdef GAME_DLL
//NDebugOverlay::Line( vTracePos, vTracePos + Vector( 0.0f, 0.0f, 1.0f ), 255, 0, 0, true, 0.0f );
//NDebugOverlay::BoxAngles( pMyProp->GetCollisionOrigin(), pMyProp->OBBMins(), pMyProp->OBBMaxs(), pMyProp->GetCollisionAngles(), 255, 255, 0, true, 0.0f );
#endif
if ( IsRayIntersectingOBB( ray, pMyProp->GetCollisionOrigin(), pMyProp->GetCollisionAngles(), pMyProp->OBBMins(), pMyProp->OBBMaxs() ) )
{
// Under the crosshair! Give it a high number, but subtract distance from the score in case multiple things are under the crosshair.
return ( 10000 - vTracePos.DistTo( pMyProp->GetCollisionOrigin() ) );
}
}
if ( pEnt->Classify() == CLASS_ASW_BUTTON_PANEL )
{
CASW_Button_Area *pButton = static_cast< CASW_Button_Area* >( pEnt );
if ( pButton->IsWaitingForInput() )
{
// Button wants to be pushed oh so badly
return 2;
}
return 0;
}
if ( pEnt->Classify() == CLASS_ASW_COMPUTER_AREA )
{
CASW_Computer_Area *pComputer = static_cast< CASW_Computer_Area* >( pEnt );
if ( pComputer->IsWaitingForInput() )
{
// Button wants to be pushed oh so badly
return 2;
}
return 0;
}
// check if this item is usable by a marine
CASW_Weapon *pWeapon = dynamic_cast< CASW_Weapon* >( pEnt );
if ( pWeapon )
{
if ( pWeapon->AllowedToPickup( GetMarine() ) )
{
return 1;
}
else
{
return -1;
}
}
// check if this item is usable by a marine
CASW_Pickup *pPickup = dynamic_cast< CASW_Pickup* >( pEnt );
if ( pPickup )
{
if ( pPickup->AllowedToPickup( GetMarine() ) )
{
return 1;
}
else
{
return -1;
}
}
// check if this item is usable by a marine
CASW_Ammo_Drop *pAmmoDrop = dynamic_cast< CASW_Ammo_Drop* >( pEnt );
if ( pAmmoDrop )
{
if ( pAmmoDrop->AllowedToPickup( GetMarine() ) )
{
return 1;
}
else
{
return -1;
}
}
// if it's not usable, give it a priority of 0
return 0;
}
CBaseCombatCharacter *CASW_Player::ActivePlayerCombatCharacter( void )
{
CASW_Marine *pMarine = GetMarine();
if ( !pMarine )
{
return BaseClass::ActivePlayerCombatCharacter();
}
return pMarine;
}
// for switching weapons on the current marine
void CASW_Player::ASWSelectWeapon(CBaseCombatWeapon* pWeapon, int subtype)
{
if ( !pWeapon )
return;
CASW_Marine* pMarine = GetMarine();
if ( !pMarine )
{
SelectItem(pWeapon->GetName(), subtype);
return;
}
#ifndef CLIENT_DLL
m_ASWLocal.m_hAutoAimTarget.Set(NULL);
#endif
pMarine->Weapon_Switch(pWeapon, subtype);
}
bool CASW_Player::Weapon_CanUse( CBaseCombatWeapon *pWeapon )
{
CASW_Marine *pMarine = GetMarine();
if ( !pMarine )
{
return BaseClass::Weapon_CanUse( pWeapon );
}
CASW_Weapon *pASWWeapon = static_cast< CASW_Weapon* >( pWeapon );
return pASWWeapon->AllowedToPickup( pMarine );
}
CBaseCombatWeapon* CASW_Player::Weapon_OwnsThisType( const char *pszWeapon, int iSubType ) const
{
const CASW_Marine *pMarine = GetMarine();
if ( !pMarine )
{
return BaseClass::Weapon_OwnsThisType( pszWeapon, iSubType );
}
return pMarine->Weapon_OwnsThisType( pszWeapon, iSubType );
}
int CASW_Player::Weapon_GetSlot( const char *pszWeapon, int iSubType ) const
{
const CASW_Marine* pMarine = GetMarine();
if ( !pMarine )
{
return BaseClass::Weapon_GetSlot( pszWeapon, iSubType );
}
return pMarine->Weapon_GetSlot( pszWeapon, iSubType );
}
// always return horizontal pitch (pitch was used for finding distance of crosshair from the centre of screen - now it's stored in roll (can return pitch safely now?))
const QAngle& CASW_Player::EyeAngles( )
{
// revert to hl2 camera
#ifdef CLIENT_DLL
if (asw_hl2_camera.GetBool() && engine->IsPlayingDemo())
#else
if (asw_hl2_camera.GetBool())
#endif
{
return BaseClass::EyeAngles();
}
static QAngle angAdjustedEyes;
#ifdef CLIENT_DLL
if ( IsLocalPlayer ( this ) )
{
angAdjustedEyes = BaseClass::EyeAngles();
}
else
{
angAdjustedEyes = m_angEyeAngles;
}
#else
angAdjustedEyes = BaseClass::EyeAngles();
#endif
#ifdef CLIENT_DLL
if ( asw_allow_detach.GetBool() && GetMarine() )
{
return m_angEyeAngles;
}
#endif
if (GetMarine())
{
angAdjustedEyes.z = 0;
CASW_Marine* pMarine = GetMarine();
// if we're driving, return the angle
if (pMarine->IsInVehicle())
{
#ifdef CLIENT_DLL
if (pMarine->GetClientsideVehicle() && pMarine->GetClientsideVehicle()->GetEntity())
return pMarine->GetClientsideVehicle()->GetEntity()->GetAbsAngles();
#endif
if (pMarine->GetASWVehicle() && pMarine->GetASWVehicle()->GetEntity())
return pMarine->GetASWVehicle()->GetEntity()->GetAbsAngles();
}
}
return angAdjustedEyes;
}
const QAngle& CASW_Player::EyeAnglesWithCursorRoll( )
{
static QAngle angCursorEyes;
#ifdef CLIENT_DLL
if ( IsLocalPlayer ( this ) )
{
angCursorEyes = BaseClass::EyeAngles();
}
else
{
angCursorEyes = m_angEyeAngles;
}
#else
angCursorEyes = BaseClass::EyeAngles();
#endif
return angCursorEyes;
}
void CASW_Player::AvoidPhysicsProps(CUserCmd *pCmd)
{
if (GetMarine() && !GetMarine()->IsInVehicle())
GetMarine()->AvoidPhysicsProps(pCmd);
}
void CASW_Player::SetAnimation( PLAYER_ANIM playerAnim )
{
// playeranim state manages the marine animations
return;
}
Vector CASW_Player::EarPosition( void )
{
// revert to hl2 camera
#ifdef CLIENT_DLL
if (asw_hl2_camera.GetBool() && engine->IsPlayingDemo())
#else
if (asw_hl2_camera.GetBool())
#endif
{
return BaseClass::EarPosition();
}
CASW_Marine *pMarine = dynamic_cast<CASW_Marine*>(m_hMarine.Get());
if (pMarine)
{
return pMarine->EarPosition();
}
if (asw_rts_controls.GetBool())
{
return GetAbsOrigin();
}
return BaseClass::EarPosition();
}
bool CASW_Player::HasLiveMarines()
{
if (!ASWGameRules())
return false;
CASW_Game_Resource* pGameResource = ASWGameResource();
if (!pGameResource)
return false;
// loop through all marines, if we find a live one, bail
for (int i=0;i<pGameResource->GetMaxMarineResources();i++)
{
CASW_Marine_Resource* pMR = pGameResource->GetMarineResource(i);
if (!pMR || pMR->GetHealthPercent() <= 0)
continue;
if (pMR->GetCommander() == this)
return true;
}
return false;
}
bool CASW_Player::IsAlive( void )
{
return HasLiveMarines();
}
void CASW_Player::PlayerUse()
{
// Was use pressed or released?
if ( ! ((m_nButtons | m_afButtonPressed | m_afButtonReleased) & IN_USE) )
return;
if (!GetMarine() || GetMarine()->GetHealth()<=0)
return;
CASW_Marine *pMarine = GetMarine();
if ( GetNumUseEntities() > 0 )
{
CBaseEntity *pEnt = GetUseEntity( 0 );
if ( pEnt )
{
if ( m_afButtonPressed & IN_USE )
{
m_flUseKeyDownTime = gpGlobals->curtime;
m_hUseKeyDownEnt = pEnt;
}
CBaseEntity *pActivateEnt = NULL;
int nHoldType = ASW_USE_RELEASE_QUICK;
if ( m_nButtons & IN_USE )
{
if ( ( gpGlobals->curtime - m_flUseKeyDownTime ) >= ASW_USE_KEY_HOLD_SENTRY_TIME )
{
pActivateEnt = m_hUseKeyDownEnt.Get();
nHoldType = ASW_USE_HOLD_RELEASE_FULL;
}
else if ( ( gpGlobals->curtime - m_flUseKeyDownTime ) >= 0.2f )
{
pActivateEnt = m_hUseKeyDownEnt.Get();
nHoldType = ASW_USE_HOLD_START;
}
}
if ( m_afButtonReleased & IN_USE )
{
if ( m_hUseKeyDownEnt.Get() == pEnt && nHoldType != ASW_USE_HOLD_RELEASE_FULL )
{
pActivateEnt = pEnt;
nHoldType = ASW_USE_RELEASE_QUICK;
}
}
if ( pActivateEnt )
{
bool bCanTake = true;
CASW_Pickup *pItem = dynamic_cast<CASW_Pickup*>( pActivateEnt );
if ( pItem && nHoldType != ASW_USE_HOLD_START )
{
bCanTake = pItem->AllowedToPickup( GetMarine() );
if (bCanTake)
{
GetMarine()->SetStopTime( gpGlobals->curtime + 1.0f );
GetMarine()->DoAnimationEvent( PLAYERANIMEVENT_PICKUP );
}
}
else
{
CASW_Weapon *pWeapon = dynamic_cast<CASW_Weapon*>( pActivateEnt );
if ( pWeapon && nHoldType != ASW_USE_HOLD_START )
{
bCanTake = pWeapon->AllowedToPickup( GetMarine() );
if (bCanTake)
{
GetMarine()->SetStopTime( gpGlobals->curtime + 1.0f );
GetMarine()->DoAnimationEvent( PLAYERANIMEVENT_PICKUP );
}
}
else
{
CASW_Ammo_Drop *pAmmoDrop = dynamic_cast<CASW_Ammo_Drop*>( pActivateEnt );
if ( pAmmoDrop && nHoldType != ASW_USE_HOLD_START )
{
bCanTake = pAmmoDrop->AllowedToPickup( GetMarine() );
if ( bCanTake )
{
GetMarine()->SetStopTime( gpGlobals->curtime + 1.0f );
GetMarine()->DoAnimationEvent( PLAYERANIMEVENT_PICKUP );
CASW_Weapon *pWeapon = pAmmoDrop->GetAmmoUseUnits( pMarine );
if ( pWeapon )
{
int iAmmoType = pWeapon->GetPrimaryAmmoType();
int iAmmoCost = pAmmoDrop->GetAmmoUnitCost( iAmmoType );
if ( iAmmoCost < 20 )
{
EmitSound( "ASW_Ammobag.Pickup_sml" );
DispatchParticleEffect( "ammo_satchel_take_sml", pAmmoDrop->GetAbsOrigin() + Vector( 0, 0, 4 ), vec3_angle );
}
else if ( iAmmoCost < 75 )
{
EmitSound( "ASW_Ammobag.Pickup_med" );
DispatchParticleEffect( "ammo_satchel_take_med", pAmmoDrop->GetAbsOrigin() + Vector( 0, 0, 4 ), vec3_angle );
}
else
{
EmitSound( "ASW_Ammobag.Pickup_lrg" );
DispatchParticleEffect( "ammo_satchel_take_lrg", pAmmoDrop->GetAbsOrigin() + Vector( 0, 0, 4 ), vec3_angle );
}
}
}
}
}
}
#ifdef GAME_DLL
IASW_Server_Usable_Entity *pUsable = dynamic_cast<IASW_Server_Usable_Entity*>( pActivateEnt );
if ( pUsable )
{
if ( !pMarine->m_hUsingEntity.Get() || pMarine->m_hUsingEntity.Get() == pActivateEnt ) // if we're in the middle of using an entity, only allow reusing that same entity
{
pUsable->ActivateUseIcon( GetMarine(), nHoldType );
}
}
#endif
}
}
}
if ( m_afButtonReleased & IN_USE )
{
m_hUseKeyDownEnt = NULL;
m_flUseKeyDownTime = 0.0f;
}
}
void CASW_Player::StartWalking( void )
{
SetMaxSpeed( ASW_MOVEMENT_WALK_SPEED );
m_fIsWalking = true;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CASW_Player::StopWalking( void )
{
SetMaxSpeed( ASW_MOVEMENT_NORM_SPEED );
m_fIsWalking = false;
}
// as HL2, but no sprinting
void CASW_Player::HandleSpeedChanges( void )
{
int buttonsChanged = m_afButtonPressed | m_afButtonReleased;
if( buttonsChanged & IN_WALK )
{
// The state of the WALK button has changed.
if( IsWalking() && !(m_afButtonPressed & IN_WALK) )
{
StopWalking();
}
else if( !IsWalking() && (m_afButtonPressed & IN_WALK) && !(m_nButtons & IN_DUCK) )
{
StartWalking();
}
}
if ( IsWalking() && !(m_nButtons & IN_WALK) )
StopWalking();
}
CBaseEntity* CASW_Player::GetSoundscapeListener()
{
if (GetMarine())
return GetMarine();
if (GetSpectatingMarine())
return GetSpectatingMarine();
return this;
}