You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
375 lines
8.2 KiB
375 lines
8.2 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
// |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "weapon_dodbasebomb.h" |
|
|
|
|
|
#ifdef CLIENT_DLL |
|
#include "c_dod_player.h" |
|
#else |
|
#include "dod_player.h" |
|
#include "dod_bombtarget.h" |
|
#include "collisionutils.h" |
|
#include "in_buttons.h" |
|
#endif |
|
|
|
|
|
IMPLEMENT_NETWORKCLASS_ALIASED( DODBaseBombWeapon, DT_BaseBombWeapon ) |
|
|
|
|
|
BEGIN_NETWORK_TABLE( CDODBaseBombWeapon, DT_BaseBombWeapon ) |
|
|
|
#ifdef CLIENT_DLL |
|
//RecvPropBool( RECVINFO(m_bDeployed) ) |
|
#else |
|
//SendPropBool( SENDINFO(m_bDeployed) ) |
|
#endif |
|
|
|
END_NETWORK_TABLE() |
|
|
|
|
|
BEGIN_PREDICTION_DATA( CDODBaseBombWeapon ) |
|
END_PREDICTION_DATA() |
|
|
|
#ifndef CLIENT_DLL |
|
|
|
BEGIN_DATADESC( CDODBaseBombWeapon ) |
|
END_DATADESC() |
|
|
|
#endif |
|
|
|
LINK_ENTITY_TO_CLASS( weapon_basebomb, CDODBaseBombWeapon ); |
|
PRECACHE_WEAPON_REGISTER( weapon_basebomb ); |
|
|
|
acttable_t CDODBaseBombWeapon::m_acttable[] = |
|
{ |
|
{ ACT_PRONE_IDLE, ACT_DOD_PRONEWALK_IDLE_PISTOL, false }, //? |
|
{ ACT_PRONE_FORWARD, ACT_DOD_PRONEWALK_IDLE_PISTOL, false }, //? |
|
{ ACT_DOD_STAND_IDLE, ACT_DOD_STAND_IDLE_TNT, false }, |
|
{ ACT_DOD_CROUCH_IDLE, ACT_DOD_CROUCH_IDLE_TNT, false }, //? |
|
{ ACT_DOD_CROUCHWALK_IDLE, ACT_DOD_CROUCHWALK_IDLE_TNT, false }, |
|
{ ACT_DOD_WALK_IDLE, ACT_DOD_WALK_IDLE_TNT, false }, |
|
{ ACT_DOD_RUN_IDLE, ACT_DOD_RUN_IDLE_TNT, false }, |
|
{ ACT_SPRINT, ACT_DOD_SPRINT_IDLE_TNT, false }, |
|
|
|
// Hand Signals |
|
{ ACT_DOD_HS_IDLE, ACT_DOD_HS_IDLE_PISTOL, false }, |
|
{ ACT_DOD_HS_CROUCH, ACT_DOD_HS_CROUCH_PISTOL, false }, |
|
}; |
|
|
|
IMPLEMENT_ACTTABLE( CDODBaseBombWeapon ); |
|
|
|
CDODBaseBombWeapon::CDODBaseBombWeapon() |
|
{ |
|
} |
|
|
|
void CDODBaseBombWeapon::Spawn( ) |
|
{ |
|
WEAPON_FILE_INFO_HANDLE hWpnInfo = LookupWeaponInfoSlot( GetClassname() ); |
|
|
|
Assert( hWpnInfo != GetInvalidWeaponInfoHandle() ); |
|
|
|
CDODWeaponInfo *pWeaponInfo = dynamic_cast< CDODWeaponInfo* >( GetFileWeaponInfoFromHandle( hWpnInfo ) ); |
|
|
|
Assert( pWeaponInfo && "Failed to get CDODWeaponInfo in weapon spawn" ); |
|
|
|
m_pWeaponInfo = pWeaponInfo; |
|
|
|
SetPlanting( false ); |
|
|
|
BaseClass::Spawn(); |
|
} |
|
|
|
void CDODBaseBombWeapon::Precache() |
|
{ |
|
BaseClass::Precache(); |
|
} |
|
|
|
bool CDODBaseBombWeapon::Deploy( ) |
|
{ |
|
#ifdef CLIENT_DLL |
|
CDODPlayer *pPlayer = GetDODPlayerOwner(); |
|
|
|
if ( pPlayer ) |
|
{ |
|
pPlayer->HintMessage( HINT_BOMB_FIRST_SELECT ); |
|
} |
|
#endif |
|
|
|
return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), GetDrawActivity(), (char*)GetAnimPrefix() ); |
|
} |
|
|
|
void CDODBaseBombWeapon::PrimaryAttack() |
|
{ |
|
#ifndef CLIENT_DLL |
|
if ( IsPlanting() ) |
|
{ |
|
CDODBombTarget *pTarget = (CDODBombTarget *)m_hBombTarget.Get(); |
|
CBasePlayer *pPlayer = GetPlayerOwner(); |
|
|
|
if ( !pTarget || !pPlayer ) |
|
{ |
|
CancelPlanting(); |
|
return; |
|
} |
|
|
|
if ( pTarget->CanPlantHere( GetDODPlayerOwner() ) == false ) |
|
{ |
|
// if the target is not active anymore, cancel ( someone planted there already? ) |
|
CancelPlanting(); |
|
} |
|
else if ( ( pTarget->GetAbsOrigin() - pPlayer->WorldSpaceCenter() ).Length() > DOD_BOMB_PLANT_RADIUS ) |
|
{ |
|
// if we're too far away, cancel |
|
CancelPlanting(); |
|
} |
|
else if ( IsLookingAtBombTarget( pPlayer, pTarget ) == false || ( pPlayer->GetFlags() & FL_ONGROUND ) == 0 ) |
|
{ |
|
// not looking at the target anymore |
|
CancelPlanting(); |
|
} |
|
else if ( gpGlobals->curtime > m_flPlantCompleteTime ) |
|
{ |
|
// we finished the plant |
|
CompletePlant(); |
|
} |
|
else |
|
{ |
|
m_flNextPlantCheck = gpGlobals->curtime + 0.2; |
|
} |
|
|
|
return; |
|
} |
|
|
|
// find nearby, visible bomb targets |
|
CBaseEntity *pEnt = NULL; |
|
CDODBombTarget *pBestTarget = NULL; |
|
|
|
float flBestDist = FLT_MAX; |
|
|
|
CDODPlayer *pPlayer = GetDODPlayerOwner(); |
|
|
|
if ( !pPlayer ) |
|
return; |
|
|
|
while( ( pEnt = gEntList.FindEntityByClassname( pEnt, "dod_bomb_target" ) ) != NULL ) |
|
{ |
|
CDODBombTarget *pTarget = static_cast<CDODBombTarget *>( pEnt ); |
|
|
|
if ( !pTarget->CanPlantHere( pPlayer ) ) |
|
continue; |
|
|
|
Vector pos = pPlayer->WorldSpaceCenter(); |
|
|
|
float flDist = ( pos - pTarget->GetAbsOrigin() ).Length(); |
|
|
|
// if we are looking directly at a bomb target and it is within our radius, that automatically wins |
|
if ( flDist < flBestDist && |
|
flDist < DOD_BOMB_PLANT_RADIUS && |
|
IsLookingAtBombTarget( pPlayer, pTarget ) && |
|
( pPlayer->GetFlags() & FL_ONGROUND ) ) |
|
{ |
|
flBestDist = flDist; |
|
pBestTarget = pTarget; |
|
} |
|
} |
|
|
|
if ( pBestTarget ) |
|
{ |
|
StartPlanting( pBestTarget ); |
|
} |
|
|
|
m_flNextPlantCheck = gpGlobals->curtime + 0.2; |
|
|
|
// true if the player is not holding primary attack |
|
m_bUsePlant = !( pPlayer->m_nButtons & (IN_ATTACK|IN_ATTACK2) ); |
|
#endif |
|
} |
|
|
|
void CDODBaseBombWeapon::SecondaryAttack() |
|
{ |
|
PrimaryAttack(); |
|
} |
|
|
|
#ifndef CLIENT_DLL |
|
void CDODBaseBombWeapon::StartPlanting( CDODBombTarget *pTarget ) |
|
{ |
|
// we have already checked that we can plant here |
|
|
|
// store a pointer to the target we're bombing |
|
m_hBombTarget = pTarget; |
|
|
|
// must do this after setting the bomb target as we tell the planter |
|
// what target they are at |
|
SetPlanting( true ); |
|
|
|
// set the timer for when we'll be done |
|
m_flPlantCompleteTime = gpGlobals->curtime + DOD_BOMB_PLANT_TIME; |
|
|
|
// play the planting animation |
|
SendWeaponAnim( ACT_VM_PRIMARYATTACK ); |
|
|
|
CDODPlayer *pPlayer = GetDODPlayerOwner(); |
|
|
|
if ( pPlayer ) |
|
{ |
|
pPlayer->DoAnimationEvent( PLAYERANIMEVENT_PLANT_TNT ); |
|
|
|
pPlayer->SetMaxSpeed( 1 ); |
|
|
|
pPlayer->SetProgressBarTime( DOD_BOMB_PLANT_TIME ); |
|
} |
|
} |
|
|
|
bool CDODBaseBombWeapon::CancelPlanting( void ) |
|
{ |
|
bool bHolster = false; |
|
|
|
SetPlanting( false ); |
|
|
|
// play a stop animation |
|
SendWeaponAnim( ACT_VM_IDLE ); |
|
|
|
CDODPlayer *pPlayer = GetDODPlayerOwner(); |
|
|
|
if ( pPlayer ) |
|
{ |
|
pPlayer->DoAnimationEvent( PLAYERANIMEVENT_CANCEL_GESTURES ); |
|
|
|
// restore player speed |
|
pPlayer->SetMaxSpeed( 600 ); |
|
|
|
pPlayer->ResetProgressBar(); |
|
|
|
if ( m_bUsePlant ) |
|
{ |
|
pPlayer->SelectLastItem(); |
|
|
|
bHolster = true; |
|
} |
|
} |
|
|
|
return bHolster; |
|
} |
|
|
|
void CDODBaseBombWeapon::CompletePlant( void ) |
|
{ |
|
CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() ); |
|
|
|
if ( pPlayer ) |
|
{ |
|
SetPlanting( false ); |
|
|
|
// restore player speed |
|
GetDODPlayerOwner()->SetMaxSpeed( 600 ); |
|
|
|
// Tell the target that we finished planting the bomb |
|
((CDODBombTarget *)m_hBombTarget.Get())->CompletePlanting( pPlayer ); |
|
|
|
// destroy the bomb weapon |
|
pPlayer->Weapon_Drop( this, NULL, NULL ); |
|
UTIL_Remove(this); |
|
|
|
pPlayer->ResetProgressBar(); |
|
|
|
pPlayer->SelectLastItem(); |
|
} |
|
} |
|
|
|
bool CDODBaseBombWeapon::IsLookingAtBombTarget( CBasePlayer *pPlayer, CDODBombTarget *pTarget ) |
|
{ |
|
Vector forward; |
|
AngleVectors( pPlayer->EyeAngles(), &forward ); |
|
|
|
Vector toBomb = pTarget->GetAbsOrigin() - pPlayer->EyePosition(); |
|
toBomb.NormalizeInPlace(); |
|
|
|
return ( DotProduct( forward, toBomb ) >= 0.8 ); |
|
} |
|
|
|
#endif |
|
|
|
void CDODBaseBombWeapon::ItemPostFrame() |
|
{ |
|
#ifndef CLIENT_DLL |
|
CBasePlayer *pPlayer = GetPlayerOwner(); |
|
|
|
if ( !pPlayer ) |
|
return; |
|
|
|
if ( pPlayer->m_nButtons & (IN_ATTACK|IN_ATTACK2) ) |
|
{ |
|
PrimaryAttack(); |
|
} |
|
// Only use the time check if we are planting with the +use key |
|
// adds a slight lag to breaking the player lock otherwise |
|
else if ( !m_bUsePlant || m_flNextPlantCheck < gpGlobals->curtime ) |
|
{ |
|
if ( IsPlanting() ) |
|
{ |
|
// reset all planting |
|
bool bHolster = CancelPlanting(); |
|
|
|
// sometimes after canceling we put the weapon away and switch |
|
// to our last weapon. In that case, we don't want to send any more |
|
// anim calls b/c it confuses the client. |
|
if ( bHolster ) |
|
{ |
|
// we've put this weapon away, stop everything |
|
return; |
|
} |
|
|
|
// anim now |
|
m_flTimeWeaponIdle = 0; |
|
} |
|
|
|
// idle |
|
if (m_flTimeWeaponIdle > gpGlobals->curtime) |
|
return; |
|
|
|
SendWeaponAnim( GetIdleActivity() ); |
|
|
|
m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration(); |
|
|
|
// if we're not planting, why do we have the bomb out? |
|
// switch to our next best weapon |
|
pPlayer->SelectLastItem(); |
|
} |
|
|
|
#endif // CLIENT_DLL |
|
} |
|
|
|
bool CDODBaseBombWeapon::Holster( CBaseCombatWeapon *pSwitchingTo ) |
|
{ |
|
#ifndef CLIENT_DLL |
|
if ( IsPlanting() ) |
|
CancelPlanting(); |
|
#endif |
|
|
|
return BaseClass::Holster( pSwitchingTo ); |
|
} |
|
|
|
void CDODBaseBombWeapon::SetPlanting( bool bPlanting ) |
|
{ |
|
m_bPlanting = bPlanting; |
|
|
|
#ifndef CLIENT_DLL |
|
CDODPlayer *pPlayer = GetDODPlayerOwner(); |
|
|
|
if ( pPlayer ) |
|
{ |
|
pPlayer->SetPlanting( m_bPlanting ? (CDODBombTarget *)m_hBombTarget.Get() : NULL ); |
|
} |
|
#endif |
|
} |
|
|
|
bool CDODBaseBombWeapon::IsPlanting( void ) |
|
{ |
|
return m_bPlanting; |
|
} |