aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/server/hl2/weapon_slam.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/server/hl2/weapon_slam.cpp
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/server/hl2/weapon_slam.cpp')
-rw-r--r--mp/src/game/server/hl2/weapon_slam.cpp1992
1 files changed, 996 insertions, 996 deletions
diff --git a/mp/src/game/server/hl2/weapon_slam.cpp b/mp/src/game/server/hl2/weapon_slam.cpp
index 7a5ac82b..958282fe 100644
--- a/mp/src/game/server/hl2/weapon_slam.cpp
+++ b/mp/src/game/server/hl2/weapon_slam.cpp
@@ -1,996 +1,996 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================//
-
-#include "cbase.h"
-#include "basehlcombatweapon.h"
-#include "player.h"
-#include "gamerules.h"
-#include "grenade_tripmine.h"
-#include "grenade_satchel.h"
-#include "entitylist.h"
-#include "weapon_slam.h"
-#include "npcevent.h"
-#include "in_buttons.h"
-#include "engine/IEngineSound.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-#define SLAM_PRIMARY_VOLUME 450
-
-BEGIN_DATADESC( CWeapon_SLAM )
-
- DEFINE_FIELD( m_tSlamState, FIELD_INTEGER ),
- DEFINE_FIELD( m_bDetonatorArmed, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_bNeedDetonatorDraw, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_bNeedDetonatorHolster, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_bNeedReload, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_bClearReload, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_bThrowSatchel, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_bAttachSatchel, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_bAttachTripmine, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_flWallSwitchTime, FIELD_TIME ),
-
- // Function Pointers
- DEFINE_FUNCTION( SLAMThink ),
- DEFINE_FUNCTION( SlamTouch ),
-
-END_DATADESC()
-
-
-IMPLEMENT_SERVERCLASS_ST(CWeapon_SLAM, DT_Weapon_SLAM)
-END_SEND_TABLE()
-
-LINK_ENTITY_TO_CLASS( weapon_slam, CWeapon_SLAM );
-PRECACHE_WEAPON_REGISTER(weapon_slam);
-
-acttable_t CWeapon_SLAM::m_acttable[] =
-{
- { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, true },
-};
-
-IMPLEMENT_ACTTABLE(CWeapon_SLAM);
-
-
-void CWeapon_SLAM::Spawn( )
-{
- BaseClass::Spawn();
-
- Precache( );
-
- UTIL_SetSize(this, Vector(-4,-4,-2),Vector(4,4,2));
-
- FallInit();// get ready to fall down
-
- SetThink( NULL );
-
- m_tSlamState = SLAM_TRIPMINE_READY;
- m_flWallSwitchTime = 0;
-
- // Give 1 piece of default ammo when first picked up
- m_iClip2 = 1;
-}
-
-void CWeapon_SLAM::Precache( void )
-{
- BaseClass::Precache();
-
- UTIL_PrecacheOther( "npc_tripmine" );
- UTIL_PrecacheOther( "npc_satchel" );
-
- PrecacheScriptSound( "Weapon_SLAM.ThrowMode" );
- PrecacheScriptSound( "Weapon_SLAM.TripMineMode" );
- PrecacheScriptSound( "Weapon_SLAM.SatchelDetonate" );
- PrecacheScriptSound( "Weapon_SLAM.TripMineAttach" );
- PrecacheScriptSound( "Weapon_SLAM.SatchelThrow" );
- PrecacheScriptSound( "Weapon_SLAM.SatchelAttach" );
-
-}
-
-//------------------------------------------------------------------------------
-// Purpose : Override to use slam's pickup touch function
-// Input :
-// Output :
-//------------------------------------------------------------------------------
-void CWeapon_SLAM::SetPickupTouch( void )
-{
- SetTouch(SlamTouch);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Override so give correct ammo
-// Input : pOther - the entity that touched me
-// Output :
-//-----------------------------------------------------------------------------
-void CWeapon_SLAM::SlamTouch( CBaseEntity *pOther )
-{
- CBaseCombatCharacter* pBCC = ToBaseCombatCharacter( pOther );
-
- // Can I even pick stuff up?
- if ( pBCC && !pBCC->IsAllowedToPickupWeapons() )
- return;
-
- // ---------------------------------------------------
- // First give weapon to touching entity if allowed
- // ---------------------------------------------------
- BaseClass::DefaultTouch(pOther);
-
- // ----------------------------------------------------
- // Give slam ammo if touching client
- // ----------------------------------------------------
- if (pOther->GetFlags() & FL_CLIENT)
- {
- // ------------------------------------------------
- // If already owned weapon of this type remove me
- // ------------------------------------------------
- CWeapon_SLAM* oldWeapon = (CWeapon_SLAM*)pBCC->Weapon_OwnsThisType( GetClassname() );
- if (oldWeapon != this)
- {
- UTIL_Remove( this );
- }
- else
- {
- pBCC->GiveAmmo( 1, m_iSecondaryAmmoType );
- SetThink(NULL);
- }
- }
-}
-
-//------------------------------------------------------------------------------
-// Purpose :
-// Input :
-// Output :
-//------------------------------------------------------------------------------
-bool CWeapon_SLAM::Holster( CBaseCombatWeapon *pSwitchingTo )
-{
- SetThink(NULL);
- return BaseClass::Holster(pSwitchingTo);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: SLAM has no reload, but must call weapon idle to update state
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-bool CWeapon_SLAM::Reload( void )
-{
- WeaponIdle( );
- return true;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CWeapon_SLAM::PrimaryAttack( void )
-{
- CBaseCombatCharacter *pOwner = GetOwner();
- if (!pOwner)
- {
- return;
- }
-
- if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0)
- {
- return;
- }
-
- switch (m_tSlamState)
- {
- case SLAM_TRIPMINE_READY:
- if (CanAttachSLAM())
- {
- StartTripmineAttach();
- }
- break;
- case SLAM_SATCHEL_THROW:
- StartSatchelThrow();
- break;
- case SLAM_SATCHEL_ATTACH:
- StartSatchelAttach();
- break;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Secondary attack switches between satchel charge and tripmine mode
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CWeapon_SLAM::SecondaryAttack( void )
-{
- return; // Nothin for now. SLAM's just a tripmine.
-
- CBaseCombatCharacter *pOwner = GetOwner();
- if (!pOwner)
- {
- return;
- }
-
- if (m_bDetonatorArmed)
- {
- StartSatchelDetonate();
- }
- else if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) > 0)
- {
- if (m_tSlamState == SLAM_TRIPMINE_READY)
- {
- // Play sound for going to throw mode
- EmitSound( "Weapon_SLAM.ThrowMode" );
-
- if (CanAttachSLAM())
- {
- SetSlamState(SLAM_SATCHEL_ATTACH);
- SendWeaponAnim( ACT_SLAM_TRIPMINE_TO_STICKWALL_ND );
- }
- else
- {
- SetSlamState(SLAM_SATCHEL_THROW);
- SendWeaponAnim( ACT_SLAM_TRIPMINE_TO_THROW_ND );
- }
- }
- else
- {
- // Play sound for going to tripmine mode
- EmitSound( "Weapon_SLAM.TripMineMode" );
-
- if (m_tSlamState == SLAM_SATCHEL_ATTACH)
- {
- SetSlamState(SLAM_TRIPMINE_READY);
- SendWeaponAnim( ACT_SLAM_STICKWALL_TO_TRIPMINE_ND );
- }
- else
- {
- SetSlamState(SLAM_TRIPMINE_READY);
- SendWeaponAnim( ACT_SLAM_THROW_TO_TRIPMINE_ND );
- }
- }
- m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CWeapon_SLAM::SatchelDetonate()
-{
- CBaseEntity *pEntity = NULL;
-
- while ((pEntity = gEntList.FindEntityByClassname( pEntity, "npc_satchel" )) != NULL)
- {
- CSatchelCharge *pSatchel = dynamic_cast<CSatchelCharge *>(pEntity);
- if (pSatchel->m_bIsLive && pSatchel->GetThrower() && GetOwner() && pSatchel->GetThrower() == GetOwner())
- {
- pSatchel->Use( GetOwner(), GetOwner(), USE_ON, 0 );
- }
- }
- // Play sound for pressing the detonator
- EmitSound( "Weapon_SLAM.SatchelDetonate" );
-
- m_bDetonatorArmed = false;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns true if there are any undetonated charges in the world
-// that belong to this player
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-bool CWeapon_SLAM::AnyUndetonatedCharges(void)
-{
- CBaseEntity *pEntity = NULL;
-
- while ((pEntity = gEntList.FindEntityByClassname( pEntity, "npc_satchel" )) != NULL)
- {
- CSatchelCharge* pSatchel = dynamic_cast<CSatchelCharge *>(pEntity);
- if (pSatchel->m_bIsLive && pSatchel->GetThrower() && pSatchel->GetThrower() == GetOwner())
- {
- return true;
- }
- }
- return false;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CWeapon_SLAM::StartSatchelDetonate()
-{
- // -----------------------------------------
- // Play detonate animation
- // -----------------------------------------
- if (m_bNeedReload)
- {
- SendWeaponAnim(ACT_SLAM_DETONATOR_DETONATE);
- }
- else if (m_tSlamState == SLAM_SATCHEL_ATTACH)
- {
- SendWeaponAnim(ACT_SLAM_STICKWALL_DETONATE);
- }
- else if (m_tSlamState == SLAM_SATCHEL_THROW)
- {
- SendWeaponAnim(ACT_SLAM_THROW_DETONATE);
- }
- else
- {
- return;
- }
- SatchelDetonate();
-
- m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
- m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CWeapon_SLAM::TripmineAttach( void )
-{
- CBaseCombatCharacter *pOwner = GetOwner();
- if (!pOwner)
- {
- return;
- }
-
- m_bAttachTripmine = false;
-
- Vector vecSrc = pOwner->Weapon_ShootPosition();
- Vector vecAiming = pOwner->EyeDirection3D();
-
- trace_t tr;
-
- UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr );
-
- if (tr.fraction < 1.0)
- {
- CBaseEntity *pEntity = tr.m_pEnt;
- if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR))
- {
- QAngle angles;
- VectorAngles(tr.plane.normal, angles);
- angles.x += 90;
-
- CBaseEntity *pEnt = CBaseEntity::Create( "npc_tripmine", tr.endpos + tr.plane.normal * 3, angles, NULL );
-
- CTripmineGrenade *pMine = (CTripmineGrenade *)pEnt;
- pMine->m_hOwner = GetOwner();
-
- pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType );
-
- EmitSound( "Weapon_SLAM.TripMineAttach" );
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CWeapon_SLAM::StartTripmineAttach( void )
-{
- // Only the player fires this way so we can cast
- CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
- if (!pPlayer)
- {
- return;
- }
-
- Vector vecSrc = pPlayer->Weapon_ShootPosition();
- Vector vecAiming = pPlayer->BodyDirection3D( );
-
- trace_t tr;
-
- UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr );
-
- if (tr.fraction < 1.0)
- {
- // ALERT( at_console, "hit %f\n", tr.flFraction );
-
- CBaseEntity *pEntity = tr.m_pEnt;
- if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR))
- {
- // player "shoot" animation
- pPlayer->SetAnimation( PLAYER_ATTACK1 );
-
- // -----------------------------------------
- // Play attach animation
- // -----------------------------------------
- SendWeaponAnim(ACT_SLAM_TRIPMINE_ATTACH);
-
- m_bNeedReload = true;
- m_bAttachTripmine = true;
- }
- else
- {
- // ALERT( at_console, "no deploy\n" );
- }
- }
- m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
- m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
-// SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CWeapon_SLAM::SatchelThrow( void )
-{
-
- m_bThrowSatchel = false;
-
- // Only the player fires this way so we can cast
- CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
-
- Vector vecSrc = pPlayer->WorldSpaceCenter();
- Vector vecFacing = pPlayer->BodyDirection3D( );
- vecSrc = vecSrc + vecFacing * 18.0;
- // BUGBUG: is this because vecSrc is not from Weapon_ShootPosition()???
- vecSrc.z += 24.0f;
-
- Vector vecThrow;
- GetOwner()->GetVelocity( &vecThrow, NULL );
- vecThrow += vecFacing * 500;
-
- // Player may have turned to face a wall during the throw anim in which case
- // we don't want to throw the SLAM into the wall
- if (CanAttachSLAM())
- {
- vecThrow = vecFacing;
- vecSrc = pPlayer->WorldSpaceCenter() + vecFacing * 5.0;
- }
-
- CSatchelCharge *pSatchel = (CSatchelCharge*)Create( "npc_satchel", vecSrc, vec3_angle, GetOwner() );
- pSatchel->SetThrower( GetOwner() );
- pSatchel->ApplyAbsVelocityImpulse( vecThrow );
- pSatchel->SetLocalAngularVelocity( QAngle( 0, 400, 0 ) );
- pSatchel->m_bIsLive = true;
- pSatchel->m_pMyWeaponSLAM = this;
-
- pPlayer->RemoveAmmo( 1, m_iSecondaryAmmoType );
-
- // Play throw sound
- EmitSound( "Weapon_SLAM.SatchelThrow" );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CWeapon_SLAM::StartSatchelThrow( void )
-{
- // -----------------------------------------
- // Play throw animation
- // -----------------------------------------
- if (m_bDetonatorArmed)
- {
- SendWeaponAnim(ACT_SLAM_THROW_THROW);
- }
- else
- {
- SendWeaponAnim(ACT_SLAM_THROW_THROW_ND);
- if (!m_bDetonatorArmed)
- {
- m_bDetonatorArmed = true;
- m_bNeedDetonatorDraw = true;
- }
- }
-
- m_bNeedReload = true;
- m_bThrowSatchel = true;
-
- m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
- m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CWeapon_SLAM::SatchelAttach( void )
-{
- CBaseCombatCharacter *pOwner = GetOwner();
- if (!pOwner)
- {
- return;
- }
-
- m_bAttachSatchel = false;
-
- Vector vecSrc = pOwner->Weapon_ShootPosition( );
- Vector vecAiming = pOwner->BodyDirection2D( );
-
- trace_t tr;
-
- UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr );
-
- if (tr.fraction < 1.0)
- {
- CBaseEntity *pEntity = tr.m_pEnt;
- if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR))
- {
- QAngle angles;
- VectorAngles(tr.plane.normal, angles);
- angles.y -= 90;
- angles.z -= 90;
- tr.endpos.z -= 6.0f;
-
- EmitSound( "Weapon_SLAM.SatchelAttach" );
-
- CSatchelCharge *pSatchel = (CSatchelCharge*)CBaseEntity::Create( "npc_satchel", tr.endpos + tr.plane.normal * 3, angles, NULL );
- pSatchel->SetMoveType( MOVETYPE_FLY ); // no gravity
- pSatchel->m_bIsAttached = true;
- pSatchel->m_bIsLive = true;
- pSatchel->SetThrower( GetOwner() );
- pSatchel->SetOwnerEntity( ((CBaseEntity*)GetOwner()) );
- pSatchel->m_pMyWeaponSLAM = this;
-
- pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType );
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CWeapon_SLAM::StartSatchelAttach( void )
-{
- CBaseCombatCharacter *pOwner = GetOwner();
- if (!pOwner)
- {
- return;
- }
-
- Vector vecSrc = pOwner->Weapon_ShootPosition( );
- Vector vecAiming = pOwner->BodyDirection2D( );
-
- trace_t tr;
-
- UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr );
-
- if (tr.fraction < 1.0)
- {
- CBaseEntity *pEntity = tr.m_pEnt;
- if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR))
- {
- // Only the player fires this way so we can cast
- CBasePlayer *pPlayer = ToBasePlayer( pOwner );
-
- // player "shoot" animation
- pPlayer->SetAnimation( PLAYER_ATTACK1 );
-
- // -----------------------------------------
- // Play attach animation
- // -----------------------------------------
- if (m_bDetonatorArmed)
- {
- SendWeaponAnim(ACT_SLAM_STICKWALL_ATTACH);
- }
- else
- {
- SendWeaponAnim(ACT_SLAM_STICKWALL_ND_ATTACH);
- if (!m_bDetonatorArmed)
- {
- m_bDetonatorArmed = true;
- m_bNeedDetonatorDraw = true;
- }
- }
-
- m_bNeedReload = true;
- m_bAttachSatchel = true;
-
- m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CWeapon_SLAM::SetSlamState( SlamState_t newState )
-{
- // Set set and set idle time so animation gets updated with state change
- m_tSlamState = newState;
- SetWeaponIdleTime( gpGlobals->curtime );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CWeapon_SLAM::SLAMThink( void )
-{
- if (m_flWallSwitchTime <= gpGlobals->curtime)
- {
- // If not in tripmine mode we need to check to see if we are close to
- // a wall. If we are we go into satchel_attach mode
- CBaseCombatCharacter *pOwner = GetOwner();
-
- if ((m_tSlamState != SLAM_TRIPMINE_READY) && (pOwner && pOwner->GetAmmoCount(m_iSecondaryAmmoType) > 0))
- {
- if (CanAttachSLAM())
- {
- if (m_tSlamState == SLAM_SATCHEL_THROW)
- {
- SetSlamState(SLAM_SATCHEL_ATTACH);
- int iAnim = m_bDetonatorArmed ? ACT_SLAM_THROW_TO_STICKWALL : ACT_SLAM_THROW_TO_STICKWALL_ND;
- SendWeaponAnim( iAnim );
- m_flWallSwitchTime = gpGlobals->curtime + SequenceDuration();
- }
- }
- else
- {
- if (m_tSlamState == SLAM_SATCHEL_ATTACH)
- {
- SetSlamState(SLAM_SATCHEL_THROW);
- int iAnim = m_bDetonatorArmed ? ACT_SLAM_STICKWALL_TO_THROW : ACT_SLAM_STICKWALL_TO_THROW_ND;
- SendWeaponAnim( iAnim );
- m_flWallSwitchTime = gpGlobals->curtime + SequenceDuration();
- }
- }
- }
- }
- SetNextThink( gpGlobals->curtime + 0.1f );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-bool CWeapon_SLAM::CanAttachSLAM( void )
-{
- CBaseCombatCharacter *pOwner = GetOwner();
- if (!pOwner)
- {
- return false;
- }
-
- Vector vecSrc = pOwner->Weapon_ShootPosition( );
- Vector vecAiming = pOwner->BodyDirection2D( );
-
- trace_t tr;
-
- Vector vecEnd = vecSrc + (vecAiming * 42);
- UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr );
-
- if (tr.fraction < 1.0)
- {
- // Don't attach to a living creature
- if (tr.m_pEnt)
- {
- CBaseEntity *pEntity = tr.m_pEnt;
- CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity );
- if (pBCC)
- {
- return false;
- }
- }
- return true;
- }
- else
- {
- return false;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Override so SLAM to so secondary attack when no secondary ammo
-// but satchel is in the world
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CWeapon_SLAM::ItemPostFrame( void )
-{
- CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
- if (!pOwner)
- {
- return;
- }
-
- if ((pOwner->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime))
- {
- SecondaryAttack();
- }
- else if (!m_bNeedReload && (pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime))
- {
- PrimaryAttack();
- }
-
- // -----------------------
- // No buttons down
- // -----------------------
- else
- {
- WeaponIdle( );
- return;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Switch to next best weapon
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CWeapon_SLAM::WeaponSwitch( void )
-{
- // Note that we may pick the SLAM again, when we switch
- // weapons, in which case we have to save and restore the
- // detonator armed state.
- // The SLAMs may be about to blow up, but haven't done so yet
- // and the deploy function will find the undetonated charges
- // and we are armed
- bool saveState = m_bDetonatorArmed;
- CBaseCombatCharacter *pOwner = GetOwner();
- pOwner->SwitchToNextBestWeapon( pOwner->GetActiveWeapon() );
- if (pOwner->GetActiveWeapon() == this)
- {
- m_bDetonatorArmed = saveState;
- }
-
- // If not armed and have no ammo
- if (!m_bDetonatorArmed && pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0)
- {
- pOwner->ClearActiveWeapon();
- }
-
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-void CWeapon_SLAM::WeaponIdle( void )
-{
- // Ready to switch animations?
- if ( HasWeaponIdleTimeElapsed() )
- {
- // Don't allow throw to attach switch unless in idle
- m_flWallSwitchTime = gpGlobals->curtime + 50;
-
- if (m_bClearReload)
- {
- m_bNeedReload = false;
- m_bClearReload = false;
- }
- CBaseCombatCharacter *pOwner = GetOwner();
- if (!pOwner)
- {
- return;
- }
-
- int iAnim = 0;
-
- if (m_bThrowSatchel)
- {
- SatchelThrow();
- if (m_bDetonatorArmed && !m_bNeedDetonatorDraw)
- {
- iAnim = ACT_SLAM_THROW_THROW2;
- }
- else
- {
- iAnim = ACT_SLAM_THROW_THROW_ND2;
- }
- }
- else if (m_bAttachSatchel)
- {
- SatchelAttach();
- if (m_bDetonatorArmed && !m_bNeedDetonatorDraw)
- {
- iAnim = ACT_SLAM_STICKWALL_ATTACH2;
- }
- else
- {
- iAnim = ACT_SLAM_STICKWALL_ND_ATTACH2;
- }
- }
- else if (m_bAttachTripmine)
- {
- TripmineAttach();
- iAnim = ACT_SLAM_TRIPMINE_ATTACH2;
- }
- else if (m_bNeedReload)
- {
- // If owner had ammo draw the correct SLAM type
- if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) > 0)
- {
- switch( m_tSlamState)
- {
- case SLAM_TRIPMINE_READY:
- {
- iAnim = ACT_SLAM_TRIPMINE_DRAW;
- }
- break;
- case SLAM_SATCHEL_ATTACH:
- {
- if (m_bNeedDetonatorHolster)
- {
- iAnim = ACT_SLAM_STICKWALL_DETONATOR_HOLSTER;
- m_bNeedDetonatorHolster = false;
- }
- else if (m_bDetonatorArmed)
- {
- iAnim = m_bNeedDetonatorDraw ? ACT_SLAM_DETONATOR_STICKWALL_DRAW : ACT_SLAM_STICKWALL_DRAW;
- m_bNeedDetonatorDraw = false;
- }
- else
- {
- iAnim = ACT_SLAM_STICKWALL_ND_DRAW;
- }
- }
- break;
- case SLAM_SATCHEL_THROW:
- {
- if (m_bNeedDetonatorHolster)
- {
- iAnim = ACT_SLAM_THROW_DETONATOR_HOLSTER;
- m_bNeedDetonatorHolster = false;
- }
- else if (m_bDetonatorArmed)
- {
- iAnim = m_bNeedDetonatorDraw ? ACT_SLAM_DETONATOR_THROW_DRAW : ACT_SLAM_THROW_DRAW;
- m_bNeedDetonatorDraw = false;
- }
- else
- {
- iAnim = ACT_SLAM_THROW_ND_DRAW;
- }
- }
- break;
- }
- m_bClearReload = true;
- }
- // If no ammo and armed, idle with only the detonator
- else if (m_bDetonatorArmed)
- {
- iAnim = m_bNeedDetonatorDraw ? ACT_SLAM_DETONATOR_DRAW : ACT_SLAM_DETONATOR_IDLE;
- m_bNeedDetonatorDraw = false;
- }
- else
- {
- pOwner->Weapon_Drop( this );
- UTIL_Remove(this);
- }
- }
- else if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0)
- {
- pOwner->Weapon_Drop( this );
- UTIL_Remove(this);
- }
-
- // If I don't need to reload just do the appropriate idle
- else
- {
- switch( m_tSlamState)
- {
- case SLAM_TRIPMINE_READY:
- {
- iAnim = ACT_SLAM_TRIPMINE_IDLE;
- }
- break;
- case SLAM_SATCHEL_THROW:
- {
- if (m_bNeedDetonatorHolster)
- {
- iAnim = ACT_SLAM_THROW_DETONATOR_HOLSTER;
- m_bNeedDetonatorHolster = false;
- }
- else
- {
- iAnim = m_bDetonatorArmed ? ACT_SLAM_THROW_IDLE : ACT_SLAM_THROW_ND_IDLE;
- m_flWallSwitchTime = 0;
- }
- }
- break;
- case SLAM_SATCHEL_ATTACH:
- {
- if (m_bNeedDetonatorHolster)
- {
- iAnim = ACT_SLAM_STICKWALL_DETONATOR_HOLSTER;
- m_bNeedDetonatorHolster = false;
- }
- else
- {
- iAnim = m_bDetonatorArmed ? ACT_SLAM_STICKWALL_IDLE : ACT_SLAM_STICKWALL_ND_IDLE;
- m_flWallSwitchTime = 0;
- }
- }
- break;
- }
- }
- SendWeaponAnim( iAnim );
- }
-}
-
-bool CWeapon_SLAM::Deploy( void )
-{
- CBaseCombatCharacter *pOwner = GetOwner();
- if (!pOwner)
- {
- return false;
- }
-
- m_bDetonatorArmed = AnyUndetonatedCharges();
-
-
- SetThink( SLAMThink );
- SetNextThink( gpGlobals->curtime + 0.1f );
-
- SetModel( GetViewModel() );
-
- // ------------------------------
- // Pick the right draw animation
- // ------------------------------
- int iActivity;
-
- // If detonator is already armed
- m_bNeedReload = false;
- if (m_bDetonatorArmed)
- {
- if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0)
- {
- iActivity = ACT_SLAM_DETONATOR_DRAW;
- m_bNeedReload = true;
- }
- else if (CanAttachSLAM())
- {
- iActivity = ACT_SLAM_DETONATOR_STICKWALL_DRAW;
- }
- else
- {
- iActivity = ACT_SLAM_DETONATOR_THROW_DRAW;
- }
- }
- else
- {
- if (CanAttachSLAM())
- {
- iActivity = ACT_SLAM_STICKWALL_ND_DRAW;
- }
- else
- {
- iActivity = ACT_SLAM_THROW_ND_DRAW;
- }
- }
-
- return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), iActivity, (char*)GetAnimPrefix() );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Constructor
-// Input :
-// Output :
-//-----------------------------------------------------------------------------
-CWeapon_SLAM::CWeapon_SLAM(void)
-{
- m_tSlamState = SLAM_SATCHEL_THROW;
- m_bDetonatorArmed = false;
- m_bNeedReload = true;
- m_bClearReload = false;
- m_bThrowSatchel = false;
- m_bAttachSatchel = false;
- m_bAttachTripmine = false;
- m_bNeedDetonatorDraw = false;
- m_bNeedDetonatorHolster = false;
-}
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "basehlcombatweapon.h"
+#include "player.h"
+#include "gamerules.h"
+#include "grenade_tripmine.h"
+#include "grenade_satchel.h"
+#include "entitylist.h"
+#include "weapon_slam.h"
+#include "npcevent.h"
+#include "in_buttons.h"
+#include "engine/IEngineSound.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+#define SLAM_PRIMARY_VOLUME 450
+
+BEGIN_DATADESC( CWeapon_SLAM )
+
+ DEFINE_FIELD( m_tSlamState, FIELD_INTEGER ),
+ DEFINE_FIELD( m_bDetonatorArmed, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_bNeedDetonatorDraw, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_bNeedDetonatorHolster, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_bNeedReload, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_bClearReload, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_bThrowSatchel, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_bAttachSatchel, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_bAttachTripmine, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_flWallSwitchTime, FIELD_TIME ),
+
+ // Function Pointers
+ DEFINE_FUNCTION( SLAMThink ),
+ DEFINE_FUNCTION( SlamTouch ),
+
+END_DATADESC()
+
+
+IMPLEMENT_SERVERCLASS_ST(CWeapon_SLAM, DT_Weapon_SLAM)
+END_SEND_TABLE()
+
+LINK_ENTITY_TO_CLASS( weapon_slam, CWeapon_SLAM );
+PRECACHE_WEAPON_REGISTER(weapon_slam);
+
+acttable_t CWeapon_SLAM::m_acttable[] =
+{
+ { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, true },
+};
+
+IMPLEMENT_ACTTABLE(CWeapon_SLAM);
+
+
+void CWeapon_SLAM::Spawn( )
+{
+ BaseClass::Spawn();
+
+ Precache( );
+
+ UTIL_SetSize(this, Vector(-4,-4,-2),Vector(4,4,2));
+
+ FallInit();// get ready to fall down
+
+ SetThink( NULL );
+
+ m_tSlamState = SLAM_TRIPMINE_READY;
+ m_flWallSwitchTime = 0;
+
+ // Give 1 piece of default ammo when first picked up
+ m_iClip2 = 1;
+}
+
+void CWeapon_SLAM::Precache( void )
+{
+ BaseClass::Precache();
+
+ UTIL_PrecacheOther( "npc_tripmine" );
+ UTIL_PrecacheOther( "npc_satchel" );
+
+ PrecacheScriptSound( "Weapon_SLAM.ThrowMode" );
+ PrecacheScriptSound( "Weapon_SLAM.TripMineMode" );
+ PrecacheScriptSound( "Weapon_SLAM.SatchelDetonate" );
+ PrecacheScriptSound( "Weapon_SLAM.TripMineAttach" );
+ PrecacheScriptSound( "Weapon_SLAM.SatchelThrow" );
+ PrecacheScriptSound( "Weapon_SLAM.SatchelAttach" );
+
+}
+
+//------------------------------------------------------------------------------
+// Purpose : Override to use slam's pickup touch function
+// Input :
+// Output :
+//------------------------------------------------------------------------------
+void CWeapon_SLAM::SetPickupTouch( void )
+{
+ SetTouch(SlamTouch);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Override so give correct ammo
+// Input : pOther - the entity that touched me
+// Output :
+//-----------------------------------------------------------------------------
+void CWeapon_SLAM::SlamTouch( CBaseEntity *pOther )
+{
+ CBaseCombatCharacter* pBCC = ToBaseCombatCharacter( pOther );
+
+ // Can I even pick stuff up?
+ if ( pBCC && !pBCC->IsAllowedToPickupWeapons() )
+ return;
+
+ // ---------------------------------------------------
+ // First give weapon to touching entity if allowed
+ // ---------------------------------------------------
+ BaseClass::DefaultTouch(pOther);
+
+ // ----------------------------------------------------
+ // Give slam ammo if touching client
+ // ----------------------------------------------------
+ if (pOther->GetFlags() & FL_CLIENT)
+ {
+ // ------------------------------------------------
+ // If already owned weapon of this type remove me
+ // ------------------------------------------------
+ CWeapon_SLAM* oldWeapon = (CWeapon_SLAM*)pBCC->Weapon_OwnsThisType( GetClassname() );
+ if (oldWeapon != this)
+ {
+ UTIL_Remove( this );
+ }
+ else
+ {
+ pBCC->GiveAmmo( 1, m_iSecondaryAmmoType );
+ SetThink(NULL);
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+// Purpose :
+// Input :
+// Output :
+//------------------------------------------------------------------------------
+bool CWeapon_SLAM::Holster( CBaseCombatWeapon *pSwitchingTo )
+{
+ SetThink(NULL);
+ return BaseClass::Holster(pSwitchingTo);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: SLAM has no reload, but must call weapon idle to update state
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+bool CWeapon_SLAM::Reload( void )
+{
+ WeaponIdle( );
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+void CWeapon_SLAM::PrimaryAttack( void )
+{
+ CBaseCombatCharacter *pOwner = GetOwner();
+ if (!pOwner)
+ {
+ return;
+ }
+
+ if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0)
+ {
+ return;
+ }
+
+ switch (m_tSlamState)
+ {
+ case SLAM_TRIPMINE_READY:
+ if (CanAttachSLAM())
+ {
+ StartTripmineAttach();
+ }
+ break;
+ case SLAM_SATCHEL_THROW:
+ StartSatchelThrow();
+ break;
+ case SLAM_SATCHEL_ATTACH:
+ StartSatchelAttach();
+ break;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Secondary attack switches between satchel charge and tripmine mode
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+void CWeapon_SLAM::SecondaryAttack( void )
+{
+ return; // Nothin for now. SLAM's just a tripmine.
+
+ CBaseCombatCharacter *pOwner = GetOwner();
+ if (!pOwner)
+ {
+ return;
+ }
+
+ if (m_bDetonatorArmed)
+ {
+ StartSatchelDetonate();
+ }
+ else if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) > 0)
+ {
+ if (m_tSlamState == SLAM_TRIPMINE_READY)
+ {
+ // Play sound for going to throw mode
+ EmitSound( "Weapon_SLAM.ThrowMode" );
+
+ if (CanAttachSLAM())
+ {
+ SetSlamState(SLAM_SATCHEL_ATTACH);
+ SendWeaponAnim( ACT_SLAM_TRIPMINE_TO_STICKWALL_ND );
+ }
+ else
+ {
+ SetSlamState(SLAM_SATCHEL_THROW);
+ SendWeaponAnim( ACT_SLAM_TRIPMINE_TO_THROW_ND );
+ }
+ }
+ else
+ {
+ // Play sound for going to tripmine mode
+ EmitSound( "Weapon_SLAM.TripMineMode" );
+
+ if (m_tSlamState == SLAM_SATCHEL_ATTACH)
+ {
+ SetSlamState(SLAM_TRIPMINE_READY);
+ SendWeaponAnim( ACT_SLAM_STICKWALL_TO_TRIPMINE_ND );
+ }
+ else
+ {
+ SetSlamState(SLAM_TRIPMINE_READY);
+ SendWeaponAnim( ACT_SLAM_THROW_TO_TRIPMINE_ND );
+ }
+ }
+ m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+void CWeapon_SLAM::SatchelDetonate()
+{
+ CBaseEntity *pEntity = NULL;
+
+ while ((pEntity = gEntList.FindEntityByClassname( pEntity, "npc_satchel" )) != NULL)
+ {
+ CSatchelCharge *pSatchel = dynamic_cast<CSatchelCharge *>(pEntity);
+ if (pSatchel->m_bIsLive && pSatchel->GetThrower() && GetOwner() && pSatchel->GetThrower() == GetOwner())
+ {
+ pSatchel->Use( GetOwner(), GetOwner(), USE_ON, 0 );
+ }
+ }
+ // Play sound for pressing the detonator
+ EmitSound( "Weapon_SLAM.SatchelDetonate" );
+
+ m_bDetonatorArmed = false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns true if there are any undetonated charges in the world
+// that belong to this player
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+bool CWeapon_SLAM::AnyUndetonatedCharges(void)
+{
+ CBaseEntity *pEntity = NULL;
+
+ while ((pEntity = gEntList.FindEntityByClassname( pEntity, "npc_satchel" )) != NULL)
+ {
+ CSatchelCharge* pSatchel = dynamic_cast<CSatchelCharge *>(pEntity);
+ if (pSatchel->m_bIsLive && pSatchel->GetThrower() && pSatchel->GetThrower() == GetOwner())
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+void CWeapon_SLAM::StartSatchelDetonate()
+{
+ // -----------------------------------------
+ // Play detonate animation
+ // -----------------------------------------
+ if (m_bNeedReload)
+ {
+ SendWeaponAnim(ACT_SLAM_DETONATOR_DETONATE);
+ }
+ else if (m_tSlamState == SLAM_SATCHEL_ATTACH)
+ {
+ SendWeaponAnim(ACT_SLAM_STICKWALL_DETONATE);
+ }
+ else if (m_tSlamState == SLAM_SATCHEL_THROW)
+ {
+ SendWeaponAnim(ACT_SLAM_THROW_DETONATE);
+ }
+ else
+ {
+ return;
+ }
+ SatchelDetonate();
+
+ m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
+ m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+void CWeapon_SLAM::TripmineAttach( void )
+{
+ CBaseCombatCharacter *pOwner = GetOwner();
+ if (!pOwner)
+ {
+ return;
+ }
+
+ m_bAttachTripmine = false;
+
+ Vector vecSrc = pOwner->Weapon_ShootPosition();
+ Vector vecAiming = pOwner->EyeDirection3D();
+
+ trace_t tr;
+
+ UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr );
+
+ if (tr.fraction < 1.0)
+ {
+ CBaseEntity *pEntity = tr.m_pEnt;
+ if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR))
+ {
+ QAngle angles;
+ VectorAngles(tr.plane.normal, angles);
+ angles.x += 90;
+
+ CBaseEntity *pEnt = CBaseEntity::Create( "npc_tripmine", tr.endpos + tr.plane.normal * 3, angles, NULL );
+
+ CTripmineGrenade *pMine = (CTripmineGrenade *)pEnt;
+ pMine->m_hOwner = GetOwner();
+
+ pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType );
+
+ EmitSound( "Weapon_SLAM.TripMineAttach" );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+void CWeapon_SLAM::StartTripmineAttach( void )
+{
+ // Only the player fires this way so we can cast
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+ if (!pPlayer)
+ {
+ return;
+ }
+
+ Vector vecSrc = pPlayer->Weapon_ShootPosition();
+ Vector vecAiming = pPlayer->BodyDirection3D( );
+
+ trace_t tr;
+
+ UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr );
+
+ if (tr.fraction < 1.0)
+ {
+ // ALERT( at_console, "hit %f\n", tr.flFraction );
+
+ CBaseEntity *pEntity = tr.m_pEnt;
+ if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR))
+ {
+ // player "shoot" animation
+ pPlayer->SetAnimation( PLAYER_ATTACK1 );
+
+ // -----------------------------------------
+ // Play attach animation
+ // -----------------------------------------
+ SendWeaponAnim(ACT_SLAM_TRIPMINE_ATTACH);
+
+ m_bNeedReload = true;
+ m_bAttachTripmine = true;
+ }
+ else
+ {
+ // ALERT( at_console, "no deploy\n" );
+ }
+ }
+ m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
+ m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
+// SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+void CWeapon_SLAM::SatchelThrow( void )
+{
+
+ m_bThrowSatchel = false;
+
+ // Only the player fires this way so we can cast
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+
+ Vector vecSrc = pPlayer->WorldSpaceCenter();
+ Vector vecFacing = pPlayer->BodyDirection3D( );
+ vecSrc = vecSrc + vecFacing * 18.0;
+ // BUGBUG: is this because vecSrc is not from Weapon_ShootPosition()???
+ vecSrc.z += 24.0f;
+
+ Vector vecThrow;
+ GetOwner()->GetVelocity( &vecThrow, NULL );
+ vecThrow += vecFacing * 500;
+
+ // Player may have turned to face a wall during the throw anim in which case
+ // we don't want to throw the SLAM into the wall
+ if (CanAttachSLAM())
+ {
+ vecThrow = vecFacing;
+ vecSrc = pPlayer->WorldSpaceCenter() + vecFacing * 5.0;
+ }
+
+ CSatchelCharge *pSatchel = (CSatchelCharge*)Create( "npc_satchel", vecSrc, vec3_angle, GetOwner() );
+ pSatchel->SetThrower( GetOwner() );
+ pSatchel->ApplyAbsVelocityImpulse( vecThrow );
+ pSatchel->SetLocalAngularVelocity( QAngle( 0, 400, 0 ) );
+ pSatchel->m_bIsLive = true;
+ pSatchel->m_pMyWeaponSLAM = this;
+
+ pPlayer->RemoveAmmo( 1, m_iSecondaryAmmoType );
+
+ // Play throw sound
+ EmitSound( "Weapon_SLAM.SatchelThrow" );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+void CWeapon_SLAM::StartSatchelThrow( void )
+{
+ // -----------------------------------------
+ // Play throw animation
+ // -----------------------------------------
+ if (m_bDetonatorArmed)
+ {
+ SendWeaponAnim(ACT_SLAM_THROW_THROW);
+ }
+ else
+ {
+ SendWeaponAnim(ACT_SLAM_THROW_THROW_ND);
+ if (!m_bDetonatorArmed)
+ {
+ m_bDetonatorArmed = true;
+ m_bNeedDetonatorDraw = true;
+ }
+ }
+
+ m_bNeedReload = true;
+ m_bThrowSatchel = true;
+
+ m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
+ m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+void CWeapon_SLAM::SatchelAttach( void )
+{
+ CBaseCombatCharacter *pOwner = GetOwner();
+ if (!pOwner)
+ {
+ return;
+ }
+
+ m_bAttachSatchel = false;
+
+ Vector vecSrc = pOwner->Weapon_ShootPosition( );
+ Vector vecAiming = pOwner->BodyDirection2D( );
+
+ trace_t tr;
+
+ UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr );
+
+ if (tr.fraction < 1.0)
+ {
+ CBaseEntity *pEntity = tr.m_pEnt;
+ if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR))
+ {
+ QAngle angles;
+ VectorAngles(tr.plane.normal, angles);
+ angles.y -= 90;
+ angles.z -= 90;
+ tr.endpos.z -= 6.0f;
+
+ EmitSound( "Weapon_SLAM.SatchelAttach" );
+
+ CSatchelCharge *pSatchel = (CSatchelCharge*)CBaseEntity::Create( "npc_satchel", tr.endpos + tr.plane.normal * 3, angles, NULL );
+ pSatchel->SetMoveType( MOVETYPE_FLY ); // no gravity
+ pSatchel->m_bIsAttached = true;
+ pSatchel->m_bIsLive = true;
+ pSatchel->SetThrower( GetOwner() );
+ pSatchel->SetOwnerEntity( ((CBaseEntity*)GetOwner()) );
+ pSatchel->m_pMyWeaponSLAM = this;
+
+ pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+void CWeapon_SLAM::StartSatchelAttach( void )
+{
+ CBaseCombatCharacter *pOwner = GetOwner();
+ if (!pOwner)
+ {
+ return;
+ }
+
+ Vector vecSrc = pOwner->Weapon_ShootPosition( );
+ Vector vecAiming = pOwner->BodyDirection2D( );
+
+ trace_t tr;
+
+ UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr );
+
+ if (tr.fraction < 1.0)
+ {
+ CBaseEntity *pEntity = tr.m_pEnt;
+ if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR))
+ {
+ // Only the player fires this way so we can cast
+ CBasePlayer *pPlayer = ToBasePlayer( pOwner );
+
+ // player "shoot" animation
+ pPlayer->SetAnimation( PLAYER_ATTACK1 );
+
+ // -----------------------------------------
+ // Play attach animation
+ // -----------------------------------------
+ if (m_bDetonatorArmed)
+ {
+ SendWeaponAnim(ACT_SLAM_STICKWALL_ATTACH);
+ }
+ else
+ {
+ SendWeaponAnim(ACT_SLAM_STICKWALL_ND_ATTACH);
+ if (!m_bDetonatorArmed)
+ {
+ m_bDetonatorArmed = true;
+ m_bNeedDetonatorDraw = true;
+ }
+ }
+
+ m_bNeedReload = true;
+ m_bAttachSatchel = true;
+
+ m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+void CWeapon_SLAM::SetSlamState( SlamState_t newState )
+{
+ // Set set and set idle time so animation gets updated with state change
+ m_tSlamState = newState;
+ SetWeaponIdleTime( gpGlobals->curtime );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+void CWeapon_SLAM::SLAMThink( void )
+{
+ if (m_flWallSwitchTime <= gpGlobals->curtime)
+ {
+ // If not in tripmine mode we need to check to see if we are close to
+ // a wall. If we are we go into satchel_attach mode
+ CBaseCombatCharacter *pOwner = GetOwner();
+
+ if ((m_tSlamState != SLAM_TRIPMINE_READY) && (pOwner && pOwner->GetAmmoCount(m_iSecondaryAmmoType) > 0))
+ {
+ if (CanAttachSLAM())
+ {
+ if (m_tSlamState == SLAM_SATCHEL_THROW)
+ {
+ SetSlamState(SLAM_SATCHEL_ATTACH);
+ int iAnim = m_bDetonatorArmed ? ACT_SLAM_THROW_TO_STICKWALL : ACT_SLAM_THROW_TO_STICKWALL_ND;
+ SendWeaponAnim( iAnim );
+ m_flWallSwitchTime = gpGlobals->curtime + SequenceDuration();
+ }
+ }
+ else
+ {
+ if (m_tSlamState == SLAM_SATCHEL_ATTACH)
+ {
+ SetSlamState(SLAM_SATCHEL_THROW);
+ int iAnim = m_bDetonatorArmed ? ACT_SLAM_STICKWALL_TO_THROW : ACT_SLAM_STICKWALL_TO_THROW_ND;
+ SendWeaponAnim( iAnim );
+ m_flWallSwitchTime = gpGlobals->curtime + SequenceDuration();
+ }
+ }
+ }
+ }
+ SetNextThink( gpGlobals->curtime + 0.1f );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+bool CWeapon_SLAM::CanAttachSLAM( void )
+{
+ CBaseCombatCharacter *pOwner = GetOwner();
+ if (!pOwner)
+ {
+ return false;
+ }
+
+ Vector vecSrc = pOwner->Weapon_ShootPosition( );
+ Vector vecAiming = pOwner->BodyDirection2D( );
+
+ trace_t tr;
+
+ Vector vecEnd = vecSrc + (vecAiming * 42);
+ UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr );
+
+ if (tr.fraction < 1.0)
+ {
+ // Don't attach to a living creature
+ if (tr.m_pEnt)
+ {
+ CBaseEntity *pEntity = tr.m_pEnt;
+ CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity );
+ if (pBCC)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Override so SLAM to so secondary attack when no secondary ammo
+// but satchel is in the world
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+void CWeapon_SLAM::ItemPostFrame( void )
+{
+ CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
+ if (!pOwner)
+ {
+ return;
+ }
+
+ if ((pOwner->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime))
+ {
+ SecondaryAttack();
+ }
+ else if (!m_bNeedReload && (pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime))
+ {
+ PrimaryAttack();
+ }
+
+ // -----------------------
+ // No buttons down
+ // -----------------------
+ else
+ {
+ WeaponIdle( );
+ return;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Switch to next best weapon
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+void CWeapon_SLAM::WeaponSwitch( void )
+{
+ // Note that we may pick the SLAM again, when we switch
+ // weapons, in which case we have to save and restore the
+ // detonator armed state.
+ // The SLAMs may be about to blow up, but haven't done so yet
+ // and the deploy function will find the undetonated charges
+ // and we are armed
+ bool saveState = m_bDetonatorArmed;
+ CBaseCombatCharacter *pOwner = GetOwner();
+ pOwner->SwitchToNextBestWeapon( pOwner->GetActiveWeapon() );
+ if (pOwner->GetActiveWeapon() == this)
+ {
+ m_bDetonatorArmed = saveState;
+ }
+
+ // If not armed and have no ammo
+ if (!m_bDetonatorArmed && pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0)
+ {
+ pOwner->ClearActiveWeapon();
+ }
+
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+void CWeapon_SLAM::WeaponIdle( void )
+{
+ // Ready to switch animations?
+ if ( HasWeaponIdleTimeElapsed() )
+ {
+ // Don't allow throw to attach switch unless in idle
+ m_flWallSwitchTime = gpGlobals->curtime + 50;
+
+ if (m_bClearReload)
+ {
+ m_bNeedReload = false;
+ m_bClearReload = false;
+ }
+ CBaseCombatCharacter *pOwner = GetOwner();
+ if (!pOwner)
+ {
+ return;
+ }
+
+ int iAnim = 0;
+
+ if (m_bThrowSatchel)
+ {
+ SatchelThrow();
+ if (m_bDetonatorArmed && !m_bNeedDetonatorDraw)
+ {
+ iAnim = ACT_SLAM_THROW_THROW2;
+ }
+ else
+ {
+ iAnim = ACT_SLAM_THROW_THROW_ND2;
+ }
+ }
+ else if (m_bAttachSatchel)
+ {
+ SatchelAttach();
+ if (m_bDetonatorArmed && !m_bNeedDetonatorDraw)
+ {
+ iAnim = ACT_SLAM_STICKWALL_ATTACH2;
+ }
+ else
+ {
+ iAnim = ACT_SLAM_STICKWALL_ND_ATTACH2;
+ }
+ }
+ else if (m_bAttachTripmine)
+ {
+ TripmineAttach();
+ iAnim = ACT_SLAM_TRIPMINE_ATTACH2;
+ }
+ else if (m_bNeedReload)
+ {
+ // If owner had ammo draw the correct SLAM type
+ if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) > 0)
+ {
+ switch( m_tSlamState)
+ {
+ case SLAM_TRIPMINE_READY:
+ {
+ iAnim = ACT_SLAM_TRIPMINE_DRAW;
+ }
+ break;
+ case SLAM_SATCHEL_ATTACH:
+ {
+ if (m_bNeedDetonatorHolster)
+ {
+ iAnim = ACT_SLAM_STICKWALL_DETONATOR_HOLSTER;
+ m_bNeedDetonatorHolster = false;
+ }
+ else if (m_bDetonatorArmed)
+ {
+ iAnim = m_bNeedDetonatorDraw ? ACT_SLAM_DETONATOR_STICKWALL_DRAW : ACT_SLAM_STICKWALL_DRAW;
+ m_bNeedDetonatorDraw = false;
+ }
+ else
+ {
+ iAnim = ACT_SLAM_STICKWALL_ND_DRAW;
+ }
+ }
+ break;
+ case SLAM_SATCHEL_THROW:
+ {
+ if (m_bNeedDetonatorHolster)
+ {
+ iAnim = ACT_SLAM_THROW_DETONATOR_HOLSTER;
+ m_bNeedDetonatorHolster = false;
+ }
+ else if (m_bDetonatorArmed)
+ {
+ iAnim = m_bNeedDetonatorDraw ? ACT_SLAM_DETONATOR_THROW_DRAW : ACT_SLAM_THROW_DRAW;
+ m_bNeedDetonatorDraw = false;
+ }
+ else
+ {
+ iAnim = ACT_SLAM_THROW_ND_DRAW;
+ }
+ }
+ break;
+ }
+ m_bClearReload = true;
+ }
+ // If no ammo and armed, idle with only the detonator
+ else if (m_bDetonatorArmed)
+ {
+ iAnim = m_bNeedDetonatorDraw ? ACT_SLAM_DETONATOR_DRAW : ACT_SLAM_DETONATOR_IDLE;
+ m_bNeedDetonatorDraw = false;
+ }
+ else
+ {
+ pOwner->Weapon_Drop( this );
+ UTIL_Remove(this);
+ }
+ }
+ else if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0)
+ {
+ pOwner->Weapon_Drop( this );
+ UTIL_Remove(this);
+ }
+
+ // If I don't need to reload just do the appropriate idle
+ else
+ {
+ switch( m_tSlamState)
+ {
+ case SLAM_TRIPMINE_READY:
+ {
+ iAnim = ACT_SLAM_TRIPMINE_IDLE;
+ }
+ break;
+ case SLAM_SATCHEL_THROW:
+ {
+ if (m_bNeedDetonatorHolster)
+ {
+ iAnim = ACT_SLAM_THROW_DETONATOR_HOLSTER;
+ m_bNeedDetonatorHolster = false;
+ }
+ else
+ {
+ iAnim = m_bDetonatorArmed ? ACT_SLAM_THROW_IDLE : ACT_SLAM_THROW_ND_IDLE;
+ m_flWallSwitchTime = 0;
+ }
+ }
+ break;
+ case SLAM_SATCHEL_ATTACH:
+ {
+ if (m_bNeedDetonatorHolster)
+ {
+ iAnim = ACT_SLAM_STICKWALL_DETONATOR_HOLSTER;
+ m_bNeedDetonatorHolster = false;
+ }
+ else
+ {
+ iAnim = m_bDetonatorArmed ? ACT_SLAM_STICKWALL_IDLE : ACT_SLAM_STICKWALL_ND_IDLE;
+ m_flWallSwitchTime = 0;
+ }
+ }
+ break;
+ }
+ }
+ SendWeaponAnim( iAnim );
+ }
+}
+
+bool CWeapon_SLAM::Deploy( void )
+{
+ CBaseCombatCharacter *pOwner = GetOwner();
+ if (!pOwner)
+ {
+ return false;
+ }
+
+ m_bDetonatorArmed = AnyUndetonatedCharges();
+
+
+ SetThink( SLAMThink );
+ SetNextThink( gpGlobals->curtime + 0.1f );
+
+ SetModel( GetViewModel() );
+
+ // ------------------------------
+ // Pick the right draw animation
+ // ------------------------------
+ int iActivity;
+
+ // If detonator is already armed
+ m_bNeedReload = false;
+ if (m_bDetonatorArmed)
+ {
+ if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0)
+ {
+ iActivity = ACT_SLAM_DETONATOR_DRAW;
+ m_bNeedReload = true;
+ }
+ else if (CanAttachSLAM())
+ {
+ iActivity = ACT_SLAM_DETONATOR_STICKWALL_DRAW;
+ }
+ else
+ {
+ iActivity = ACT_SLAM_DETONATOR_THROW_DRAW;
+ }
+ }
+ else
+ {
+ if (CanAttachSLAM())
+ {
+ iActivity = ACT_SLAM_STICKWALL_ND_DRAW;
+ }
+ else
+ {
+ iActivity = ACT_SLAM_THROW_ND_DRAW;
+ }
+ }
+
+ return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), iActivity, (char*)GetAnimPrefix() );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+CWeapon_SLAM::CWeapon_SLAM(void)
+{
+ m_tSlamState = SLAM_SATCHEL_THROW;
+ m_bDetonatorArmed = false;
+ m_bNeedReload = true;
+ m_bClearReload = false;
+ m_bThrowSatchel = false;
+ m_bAttachSatchel = false;
+ m_bAttachTripmine = false;
+ m_bNeedDetonatorDraw = false;
+ m_bNeedDetonatorHolster = false;
+}