forked from vera/halflife-thewastes-sdk
1559 lines
33 KiB
C++
1559 lines
33 KiB
C++
/***
|
|
*
|
|
* Copyright (C) 2002 The Wastes Project, All Rights Reserved.
|
|
*
|
|
* This product contains software technology from Valve Software, LLC,
|
|
* Copyright © 1996-2001, Valve LLC, All rights reserved.
|
|
*
|
|
* Use, distribution, and modification of this source code and/or resulting
|
|
* object code is restricted to non-commercial enhancements to products from
|
|
* The Wastes Project. All other use, distribution, or modification is prohibited
|
|
* without written permission from The Wastes Project.
|
|
*
|
|
***/
|
|
#include "extdll.h"
|
|
#include "util.h"
|
|
#include "cbase.h"
|
|
#include "weapons.h"
|
|
#include "weaponinfo.h"
|
|
#include "player.h"
|
|
#include "soundent.h"
|
|
#include "thewastes.h"
|
|
#include "game.h"
|
|
#include "gamerules.h"
|
|
|
|
// Entity Linkage
|
|
LINK_ENTITY_TO_CLASS(weapon_beretta,CBeretta);
|
|
LINK_ENTITY_TO_CLASS(ammo_beretta,CBerettaAmmo);
|
|
LINK_ENTITY_TO_CLASS(weapon_colt,CColt);
|
|
LINK_ENTITY_TO_CLASS(ammo_colt,CColtAmmo);
|
|
|
|
LINK_ENTITY_TO_CLASS(weapon_deagle,CDesertEagle);
|
|
LINK_ENTITY_TO_CLASS(ammo_deagle,CDesertEagleAmmo);
|
|
|
|
LINK_ENTITY_TO_CLASS(weapon_ruger,CRuger);
|
|
LINK_ENTITY_TO_CLASS(ammo_ruger,CRugerAmmo);
|
|
|
|
LINK_ENTITY_TO_CLASS(weapon_handcannon,CHandcannon);
|
|
LINK_ENTITY_TO_CLASS(ammo_handcannon,CHandcannonAmmo);
|
|
|
|
/*************
|
|
Sidearm
|
|
*************/
|
|
|
|
void CSidearm::Spawn()
|
|
{
|
|
CWasteWeapon::Spawn();
|
|
|
|
Precache();
|
|
|
|
SET_MODEL(ENT(pev),GetModelW());
|
|
m_iState = SIDEARM_SHOOT;
|
|
m_iOldState = -1;
|
|
m_iAllowFire = TRUE;
|
|
m_iExtraRound = TRUE;
|
|
|
|
m_bAimReload = FALSE;
|
|
|
|
FallInit();
|
|
}
|
|
|
|
void CSidearm::Precache()
|
|
{
|
|
PRECACHE_MODEL(GetModelV());
|
|
PRECACHE_MODEL(GetModelP());
|
|
PRECACHE_MODEL(GetModelW());
|
|
|
|
PRECACHE_SOUND("weapons/whip.wav");
|
|
PRECACHE_SOUND("weapons/whip2.wav");
|
|
PRECACHE_SOUND("weapons/whip3.wav");
|
|
|
|
// For pistol whipping
|
|
PRECACHE_SOUND("weapons/cbar_hitbod1.wav");
|
|
PRECACHE_SOUND("weapons/cbar_hitbod2.wav");
|
|
PRECACHE_SOUND("weapons/cbar_hitbod3.wav");
|
|
}
|
|
|
|
int CSidearm::GetItemInfo(ItemInfo *p)
|
|
{
|
|
p->pszName = STRING(pev->classname);
|
|
p->iSlot = 1;
|
|
p->iFlags = 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
void CSidearm::PackWeapon(void *weapon_data)
|
|
{
|
|
weapon_data_t *local_data = (weapon_data_t*)weapon_data;
|
|
|
|
local_data->m_iWeaponState = m_iState;
|
|
local_data->iuser4 = m_iAllowFire;
|
|
}
|
|
|
|
void CSidearm::UnpackWeapon(void *weapon_data)
|
|
{
|
|
weapon_data_t *local_data = (weapon_data_t*)weapon_data;
|
|
|
|
m_iState = local_data->m_iWeaponState;
|
|
m_iAllowFire = local_data->iuser4;
|
|
}
|
|
|
|
void CSidearm::ItemPostFrame()
|
|
{
|
|
if ((m_fInReload) && ( m_pPlayer->m_flNextAttack <= UTIL_WeaponTimeBase() ) )
|
|
{
|
|
int j;
|
|
|
|
// complete the reload.
|
|
if(m_iId == WEAPON_RUGER)
|
|
j = Q_min( iMaxClip() - m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]);
|
|
else
|
|
j = Q_min( iMaxClip(), m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]);
|
|
|
|
// remove all ammo from gun.
|
|
if(m_iId != WEAPON_RUGER)
|
|
m_iClip = 0;
|
|
|
|
// Add them to the clip
|
|
m_iClip += j;
|
|
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= j;
|
|
#ifndef CLIENT_DLL
|
|
m_pPlayer->TabulateAmmo();
|
|
#endif
|
|
m_fInReload = FALSE;
|
|
|
|
// Go back to aim, we're done here.
|
|
if(m_bAimReload)
|
|
{
|
|
SetState(SIDEARM_AIM);
|
|
m_bAimReload = FALSE;
|
|
}
|
|
|
|
// If we're a ruger, check to see
|
|
// if we need to zoom in again.
|
|
if(m_iId == WEAPON_RUGER)
|
|
{
|
|
CRuger *pRuger = (CRuger*)this;
|
|
|
|
if(pRuger->m_bInZoom)
|
|
{
|
|
pRuger->m_bInZoom = FALSE;
|
|
pRuger->SecondaryAttack();
|
|
}
|
|
}
|
|
}
|
|
|
|
// client is trying to reload
|
|
if(m_bAimReload && m_pPlayer->m_flNextAttack <= UTIL_WeaponTimeBase())
|
|
{
|
|
Reload();
|
|
return;
|
|
}
|
|
|
|
CWasteWeapon::ItemPostFrame();
|
|
|
|
// Set allow fire mode
|
|
if(!(m_pPlayer->pev->button & IN_ATTACK))
|
|
m_iAllowFire = TRUE;
|
|
// else
|
|
// m_iAllowFire = FALSE;
|
|
}
|
|
|
|
void CSidearm::PrimaryAttack()
|
|
{
|
|
if((m_iState == SIDEARM_SHOOT || m_iState == SIDEARM_AIM) && m_iAllowFire)
|
|
PistolFire(m_fAccuracy,m_fRateOfFire);
|
|
}
|
|
|
|
void CSidearm::SecondaryAttack()
|
|
{
|
|
// Cant whip from aim mode
|
|
if(m_iState == SIDEARM_AIM)
|
|
return;
|
|
|
|
int flags;
|
|
#if defined( CLIENT_WEAPONS )
|
|
flags = FEV_NOTHOST;
|
|
#else
|
|
flags = 0;
|
|
#endif
|
|
|
|
PLAYBACK_EVENT_FULL(flags,
|
|
m_pPlayer->edict(),
|
|
m_usFire1,
|
|
0.0,
|
|
(float*)&g_vecZero,
|
|
(float*)&g_vecZero,
|
|
0.0,
|
|
0.0,
|
|
(m_iClip == 0),
|
|
0, // Whip
|
|
0,
|
|
0);
|
|
|
|
// player "shoot" animation
|
|
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
|
|
|
// Attack something
|
|
TraceResult tr;
|
|
|
|
Vector vecSrc = m_pPlayer->GetGunPosition();
|
|
Vector vecAiming = gpGlobals->v_forward;
|
|
Vector vecEnd = vecSrc + gpGlobals->v_forward * 32;
|
|
|
|
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, ENT( m_pPlayer->pev ), &tr );
|
|
|
|
#ifndef CLIENT_DLL
|
|
if ( tr.flFraction >= 1.0 )
|
|
{
|
|
UTIL_TraceHull( vecSrc, vecEnd, dont_ignore_monsters, head_hull, ENT( m_pPlayer->pev ), &tr );
|
|
if ( tr.flFraction < 1.0 )
|
|
{
|
|
// Calculate the point of intersection of the line (or hull) and the object we hit
|
|
// This is and approximation of the "best" intersection
|
|
CBaseEntity *pHit = CBaseEntity::Instance( tr.pHit );
|
|
if ( !pHit || pHit->IsBSPModel() )
|
|
FindHullIntersection( vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, m_pPlayer->edict() );
|
|
vecEnd = tr.vecEndPos; // This is the point on the actual surface (the hull could have hit space)
|
|
}
|
|
}
|
|
|
|
// hit
|
|
CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit);
|
|
|
|
ClearMultiDamage( );
|
|
|
|
// first swing does full damage TODO FIX
|
|
pEntity->TraceAttack(m_pPlayer->pev, GetWhipDmg() , gpGlobals->v_forward, &tr, DMG_CLUB|DMG_NEVERGIB );
|
|
ApplyMultiDamage( m_pPlayer->pev, m_pPlayer->pev );
|
|
|
|
if (pEntity)
|
|
{
|
|
if ( pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE )
|
|
{
|
|
// play thwack or smack sound
|
|
switch( RANDOM_LONG(0,2) )
|
|
{
|
|
case 0:
|
|
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hitbod1.wav", 1, ATTN_NORM); break;
|
|
case 1:
|
|
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hitbod2.wav", 1, ATTN_NORM); break;
|
|
case 2:
|
|
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hitbod3.wav", 1, ATTN_NORM); break;
|
|
}
|
|
m_pPlayer->m_iWeaponVolume = 128;
|
|
}
|
|
}
|
|
#endif
|
|
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5f;
|
|
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.917f;
|
|
}
|
|
|
|
void CSidearm::SpecialMode()
|
|
{
|
|
if(m_pPlayer->m_flNextAttack > UTIL_WeaponTimeBase())
|
|
return;
|
|
|
|
if(m_iState == SIDEARM_AIM)
|
|
SetState(SIDEARM_SHOOT);
|
|
else
|
|
SetState(SIDEARM_AIM);
|
|
}
|
|
|
|
void CSidearm::SetState(int statenum)
|
|
{
|
|
m_iOldState = m_iState;
|
|
|
|
switch(statenum)
|
|
{
|
|
case SIDEARM_SHOOT:
|
|
if(m_iState == SIDEARM_AIM)
|
|
{
|
|
SendWeaponAnim((m_iClip == 0) ? SPISTOL_END_AIM_EMPTY : SPISTOL_END_AIM,UseDecrement() ? 1 : 0);
|
|
}
|
|
else
|
|
SendWeaponAnim(SPISTOL_IDLE,UseDecrement() ? 1 : 0);
|
|
m_pPlayer->m_flNextAttack = m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.75;
|
|
m_iState = SIDEARM_SHOOT;
|
|
break;
|
|
case SIDEARM_AIM:
|
|
m_iState = SIDEARM_AIM;
|
|
SendWeaponAnim((m_iClip == 0) ? SPISTOL_GOTO_AIM_EMPTY : SPISTOL_GOTO_AIM,UseDecrement() ? 1 : 0);
|
|
m_pPlayer->m_flNextAttack = m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.75;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CSidearm::PistolFire(float spread,float rof)
|
|
{
|
|
if(m_iClip <= 0)
|
|
{
|
|
if(m_fFireOnEmpty)
|
|
{
|
|
PlayEmptySound();
|
|
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.3;
|
|
}
|
|
|
|
SendWeaponAnim((m_iState == SIDEARM_SHOOT) ? SPISTOL_SHOOT_EMPTY : SPISTOL_AIM_SHOOT_EMPTY,UseDecrement() ? 1 : 0);
|
|
return;
|
|
}
|
|
|
|
// Modify gun logic if we're aiming
|
|
if(m_iState == SIDEARM_AIM)
|
|
{
|
|
spread /= SIDEARM_AIMPENALTY;
|
|
rof *= SIDEARM_AIMPENALTY;
|
|
|
|
// If we are moving, incur an ADDITIONAL rof penalty
|
|
if(m_pPlayer->pev->velocity[0] != 0 || m_pPlayer->pev->velocity[1] != 0 || m_pPlayer->pev->velocity[2] != 0)
|
|
rof *= MOVING_AIMPENALTY;
|
|
}
|
|
|
|
m_iClip--;
|
|
m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH;
|
|
|
|
// player "shoot" animation
|
|
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
|
|
|
m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME;
|
|
m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;
|
|
|
|
Vector vecSrc = m_pPlayer->GetGunPosition( );
|
|
Vector vecAiming = gpGlobals->v_forward;
|
|
Vector dir;
|
|
|
|
Vector Spread;
|
|
|
|
// Accuracy modifiers
|
|
if(m_pPlayer->pev->flags & FL_DUCKING)
|
|
Spread = Vector(spread*SIDEARM_DUCKPENALTY,spread*SIDEARM_DUCKPENALTY,spread*SIDEARM_DUCKPENALTY);
|
|
else if(m_pPlayer->pev->flags & FL_ONGROUND)
|
|
Spread = Vector(spread,spread,spread);
|
|
else
|
|
Spread = Vector(spread*SIDEARM_JUMPPENALTY,spread*SIDEARM_JUMPPENALTY,spread*SIDEARM_JUMPPENALTY);
|
|
|
|
int penetration_type = 0;
|
|
|
|
switch(m_iId)
|
|
{
|
|
case WEAPON_DEAGLE:
|
|
penetration_type = P_DEAGLE; break;
|
|
case WEAPON_COLT:
|
|
penetration_type = P_COLT; break;
|
|
case WEAPON_BERETTA:
|
|
penetration_type = P_BERETTA; break;
|
|
}
|
|
|
|
dir = m_pPlayer->FireBulletsPlayer(this, 1, vecSrc, vecAiming, Spread, 8192, m_iBulletType, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed, penetration_type);
|
|
|
|
int flags;
|
|
#if defined( CLIENT_WEAPONS )
|
|
flags = FEV_NOTHOST;
|
|
#else
|
|
flags = 0;
|
|
#endif
|
|
|
|
PLAYBACK_EVENT_FULL(flags,
|
|
m_pPlayer->edict(),
|
|
m_usFire1,
|
|
0.0,
|
|
(float*)&g_vecZero,
|
|
(float*)&g_vecZero,
|
|
dir.x,
|
|
dir.y,
|
|
0,
|
|
1, // Pistol
|
|
(m_iClip == 0) ? 1 : 0,
|
|
(m_iState == SIDEARM_AIM) ? 1 : 0 );
|
|
|
|
m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + rof;
|
|
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + RANDOM_FLOAT ( 10, 15 );
|
|
|
|
m_iAllowFire = FALSE;
|
|
}
|
|
|
|
void CSidearm::SwingWeapon()
|
|
{
|
|
}
|
|
|
|
// again, here some more ruger specific hack code.
|
|
void CSidearm::Reload()
|
|
{
|
|
int iResult;
|
|
|
|
// See if we need to reload
|
|
if(m_iClip == m_iClipSize)
|
|
return;
|
|
|
|
// If we are in aim mode, HACK our way into oblivion!
|
|
if(m_iState == SIDEARM_AIM)
|
|
{
|
|
m_bAimReload = TRUE;
|
|
m_pPlayer->m_flNextAttack = m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5;
|
|
SetState(SIDEARM_SHOOT);
|
|
return;
|
|
}
|
|
|
|
// player "reload" animation
|
|
m_pPlayer->SetAnimation( PLAYER_RELOAD );
|
|
|
|
if (m_iClip == 0)
|
|
{
|
|
// ruger check - dont hold back on gun capacity like the semi's
|
|
if(m_iId == WEAPON_RUGER)
|
|
iResult = DefaultReload( m_iClipSize,RUGER_RELOAD, 4.0f);
|
|
else
|
|
{
|
|
int anim;
|
|
float timing;
|
|
|
|
switch((int)UTIL_SharedRandomFloat(m_pPlayer->random_seed,0,1))
|
|
{
|
|
case 0: anim = SPISTOL_RELOAD_EMPTY; timing = 2.955f; break;
|
|
case 1: anim = SPISTOL_RELOAD2_EMPTY; timing = 3.864f; break;
|
|
}
|
|
|
|
iResult = DefaultReload(m_iClipSize, anim, timing );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// See if we are a ruger - if not no big deal.
|
|
if(m_iId == WEAPON_RUGER)
|
|
iResult = DefaultReload( m_iClipSize, RUGER_RELOAD, 4.0f );
|
|
else
|
|
{
|
|
int anim;
|
|
int timing;
|
|
|
|
switch((int)UTIL_SharedRandomFloat(m_pPlayer->random_seed,0,1))
|
|
{
|
|
case 0: anim = SPISTOL_RELOAD; timing = 2.273f; break;
|
|
case 1: anim = SPISTOL_RELOAD2; timing = 3.41f; break;
|
|
}
|
|
|
|
iResult = DefaultReload(m_iClipSize, anim, timing );
|
|
}
|
|
}
|
|
|
|
if (iResult)
|
|
{
|
|
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + RANDOM_FLOAT ( 10, 15 );
|
|
}
|
|
else
|
|
m_bAimReload = FALSE;
|
|
}
|
|
|
|
void CSidearm::Holster(int skiplocal)
|
|
{
|
|
// In case the gun was zoomed in, or in
|
|
// aim mode, go ahead and give the
|
|
// player his movement back.
|
|
MODIFY_PLAYER_SPEED(m_pPlayer,0);
|
|
|
|
if(m_iState != SIDEARM_SHOOT)
|
|
m_iState = SIDEARM_SHOOT;
|
|
CWasteWeapon::Holster(skiplocal);
|
|
}
|
|
|
|
// Once again, ruger hacks abound!
|
|
BOOL CSidearm::Deploy()
|
|
{
|
|
if(m_iId == WEAPON_RUGER)
|
|
{
|
|
if(!DefaultDeploy(GetModelV(),GetModelP(),RUGER_DRAW,GetAnimPlayer()))
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
if(m_iClip)
|
|
{
|
|
if(!DefaultDeploy(GetModelV(),GetModelP(),SPISTOL_DRAW,GetAnimPlayer()))
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
if(!DefaultDeploy(GetModelV(),GetModelP(),SPISTOL_DRAW_EMPTY,GetAnimPlayer()))
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
m_iState = SIDEARM_SHOOT;
|
|
m_iOldState = -1;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CSidearm::PlayEmptySound()
|
|
{
|
|
if (m_iPlayEmptySound)
|
|
{
|
|
m_iPlayEmptySound = 0;
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void CSidearm::WeaponIdle()
|
|
{
|
|
ResetEmptySound();
|
|
}
|
|
|
|
void CSidearm::Drop()
|
|
{
|
|
if(m_iState != SIDEARM_SHOOT)
|
|
m_iState = SIDEARM_SHOOT; // Let the next person who picks this up start in a shoot mode.
|
|
CWasteWeapon::Drop();
|
|
}
|
|
|
|
/*************
|
|
Beretta
|
|
*************/
|
|
|
|
void CBeretta::Spawn()
|
|
{
|
|
pev->classname = MAKE_STRING("weapon_beretta");
|
|
|
|
m_iBulletType = BULLET_9MMP;
|
|
m_iId = WEAPON_BERETTA;
|
|
m_iDefaultAmmo = AMMO_GIVE_BERETTA;
|
|
m_iClipSize = CLIP_BERETTA;
|
|
|
|
m_fAccuracy = 0.05;
|
|
m_fRateOfFire = 0.225;
|
|
|
|
CSidearm::Spawn();
|
|
}
|
|
|
|
void CBeretta::Precache()
|
|
{
|
|
PRECACHE_SOUND("weapons/beretta_fire.wav");
|
|
|
|
PRECACHE_MODEL("models/shells/shell_9x18mm_lo.mdl");
|
|
PRECACHE_MODEL("models/shells/shell_9x18mm_hi.mdl");
|
|
|
|
PRECACHE_MODEL("models/shells/mag_beretta.mdl");
|
|
|
|
m_usFire1 = PRECACHE_EVENT(1,"events/beretta.sc");
|
|
|
|
CSidearm::Precache();
|
|
}
|
|
|
|
int CBeretta::GetItemInfo(ItemInfo *p)
|
|
{
|
|
p->pszAmmo1 = "9mm Parabellum";
|
|
p->iMaxAmmo1 = AMMO_MAX_BERETTA;
|
|
p->pszAmmo2 = NULL;
|
|
p->iMaxAmmo2 = -1;
|
|
p->iMaxClip = CLIP_BERETTA;
|
|
|
|
p->iPosition = 0;
|
|
|
|
p->iId = m_iId = WEAPON_BERETTA;
|
|
p->iWeight = WEIGHT_BERETTA;
|
|
|
|
return CSidearm::GetItemInfo(p);
|
|
}
|
|
|
|
float CBeretta::flGetTiltedDamage()
|
|
{
|
|
float fRet = RANDOM_FLOAT(38,48);
|
|
|
|
// 10% accuracy bonus when aiming
|
|
if(m_iState == SIDEARM_AIM)
|
|
fRet *= 1.10f;
|
|
|
|
return fRet;
|
|
}
|
|
|
|
const char *CBeretta::szGetDeathNoticeString()
|
|
{
|
|
return RANDOM_LONG(0,1) ? DEATH_BERETTA_1 : DEATH_BERETTA_2;
|
|
}
|
|
|
|
void CBeretta::AttachToPlayer( CBasePlayer *pPlayer )
|
|
{
|
|
//#ifndef CLIENT_DLL
|
|
#if 0
|
|
// TODO: Implement this code, and also implement removing akimbos
|
|
// when you drop your other guns
|
|
// See if this player already has this weapon
|
|
CBaseEntity *ent = NULL;
|
|
int iBerettaCount = 0;
|
|
|
|
while( (ent = UTIL_FindEntityInSphere( ent, pPlayer->pev->origin, 16 )) != NULL )
|
|
{
|
|
if( FStrEq( STRING(ent->pev->classname), "weapon_beretta" ) )
|
|
{
|
|
// if( ent->pev->owner == pPlayer->edict() )
|
|
iBerettaCount++;
|
|
}
|
|
}
|
|
|
|
if( iBerettaCount > 1 )
|
|
pPlayer->GiveNamedItem( "weapon_akimboberettas" );
|
|
#endif
|
|
|
|
CSidearm::AttachToPlayer( pPlayer );
|
|
}
|
|
|
|
//
|
|
// Ammo Box
|
|
//
|
|
|
|
void CBerettaAmmo::Spawn()
|
|
{
|
|
Precache();
|
|
SET_MODEL(ENT(pev),"models/ammo_beretta.mdl");
|
|
CWasteAmmo::Spawn();
|
|
}
|
|
|
|
void CBerettaAmmo::Precache()
|
|
{
|
|
PRECACHE_MODEL("models/ammo_beretta.mdl");
|
|
}
|
|
|
|
BOOL CBerettaAmmo::AddAmmo(CBaseEntity *pOther)
|
|
{
|
|
if (pOther->GiveAmmo( AMMO_GIVE_BERETTA,"9mm Parabellum",AMMO_MAX_BERETTA ) != -1)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
/*************
|
|
Colt Enforcer
|
|
*************/
|
|
|
|
void CColt::Spawn()
|
|
{
|
|
pev->classname = MAKE_STRING("weapon_colt");
|
|
|
|
m_iBulletType = BULLET_10MM;
|
|
m_iId = WEAPON_COLT;
|
|
m_iDefaultAmmo = AMMO_GIVE_COLT;
|
|
m_iClipSize = CLIP_COLT;
|
|
|
|
m_fAccuracy = 0.06;
|
|
m_fRateOfFire = 0.300;
|
|
|
|
CSidearm::Spawn();
|
|
}
|
|
|
|
void CColt::Precache()
|
|
{
|
|
PRECACHE_SOUND("weapons/colt_fire.wav");
|
|
PRECACHE_SOUND("weapons/colt_fire_empty.wav");
|
|
|
|
PRECACHE_MODEL("models/shells/shell_10mm_lo.mdl");
|
|
PRECACHE_MODEL("models/shells/shell_10mm_hi.mdl");
|
|
|
|
PRECACHE_MODEL("models/shells/mag_colt.mdl");
|
|
|
|
m_usFire1 = PRECACHE_EVENT(1,"events/colt.sc");
|
|
|
|
CSidearm::Precache();
|
|
}
|
|
|
|
int CColt::GetItemInfo(ItemInfo *p)
|
|
{
|
|
|
|
p->pszAmmo1 = ".40 S&W";
|
|
p->iMaxAmmo1 = AMMO_MAX_COLT;
|
|
p->pszAmmo2 = NULL;
|
|
p->iMaxAmmo2 = -1;
|
|
p->iMaxClip = CLIP_COLT;
|
|
|
|
p->iPosition = 1;
|
|
|
|
p->iId = m_iId = WEAPON_COLT;
|
|
p->iWeight = WEIGHT_COLT;
|
|
|
|
return CSidearm::GetItemInfo(p);
|
|
}
|
|
|
|
float CColt::flGetTiltedDamage()
|
|
{
|
|
float fRet = RANDOM_FLOAT(45,55);
|
|
|
|
// 10% accuracy bonus when aiming
|
|
if(m_iState == SIDEARM_AIM)
|
|
fRet *= 1.10f;
|
|
|
|
return fRet;
|
|
}
|
|
|
|
const char *CColt::szGetDeathNoticeString()
|
|
{
|
|
return RANDOM_LONG(0,1) ? DEATH_COLT_1 : DEATH_COLT_2;
|
|
}
|
|
|
|
//
|
|
// Ammo Box
|
|
//
|
|
void CColtAmmo::Spawn()
|
|
{
|
|
Precache();
|
|
SET_MODEL(ENT(pev),"models/ammo_colt.mdl");
|
|
CWasteAmmo::Spawn();
|
|
}
|
|
|
|
void CColtAmmo::Precache()
|
|
{
|
|
PRECACHE_MODEL("models/ammo_colt.mdl");
|
|
}
|
|
|
|
BOOL CColtAmmo::AddAmmo(CBaseEntity *pOther)
|
|
{
|
|
if (pOther->GiveAmmo( AMMO_GIVE_COLT,".40 S&W",AMMO_MAX_COLT ) != -1)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
/*************
|
|
Desert Eagle .50
|
|
*************/
|
|
|
|
void CDesertEagle::Spawn()
|
|
{
|
|
pev->classname = MAKE_STRING("weapon_deagle");
|
|
|
|
m_iBulletType = BULLET_50AE;
|
|
m_iId = WEAPON_DEAGLE;
|
|
m_iDefaultAmmo = AMMO_GIVE_DEAGLE;
|
|
m_iClipSize = CLIP_DEAGLE;
|
|
|
|
CSidearm::Spawn();
|
|
|
|
m_fAccuracy = 0.0625;
|
|
m_fRateOfFire = 0.385;
|
|
}
|
|
|
|
void CDesertEagle::Precache()
|
|
{
|
|
PRECACHE_SOUND("weapons/deagle_fire.wav");
|
|
PRECACHE_SOUND("weapons/deagle_fire_empty.wav");
|
|
|
|
m_usFire1 = PRECACHE_EVENT(1,"events/deagle.sc");
|
|
|
|
CSidearm::Precache();
|
|
|
|
PRECACHE_MODEL("models/shells/shell_50AE_lo.mdl");
|
|
PRECACHE_MODEL("models/shells/shell_50AE_hi.mdl");
|
|
|
|
PRECACHE_MODEL("models/shells/mag_deagle.mdl");
|
|
}
|
|
|
|
int CDesertEagle::GetItemInfo(ItemInfo *p)
|
|
{
|
|
|
|
p->pszAmmo1 = ".50 AE";
|
|
p->iMaxAmmo1 = AMMO_MAX_DEAGLE;
|
|
p->pszAmmo2 = NULL;
|
|
p->iMaxAmmo2 = -1;
|
|
p->iMaxClip = CLIP_DEAGLE;
|
|
|
|
p->iPosition = 2;
|
|
|
|
p->iId = m_iId = WEAPON_DEAGLE;
|
|
p->iWeight = WEIGHT_DEAGLE;
|
|
|
|
return CSidearm::GetItemInfo(p);
|
|
}
|
|
|
|
float CDesertEagle::flGetTiltedDamage()
|
|
{
|
|
float fRet = RANDOM_FLOAT(50,60);
|
|
|
|
// 10% accuracy bonus when aiming
|
|
if(m_iState == SIDEARM_AIM)
|
|
fRet *= 1.10f;
|
|
|
|
return fRet;
|
|
}
|
|
|
|
const char *CDesertEagle::szGetDeathNoticeString()
|
|
{
|
|
return RANDOM_LONG(0,1) ? DEATH_DEAGLE_1 : DEATH_DEAGLE_2;
|
|
}
|
|
|
|
void CDesertEagle::SwingWeapon()
|
|
{
|
|
CSidearm::SwingWeapon();
|
|
|
|
// Desert Eagle pistol whipping takes longer to recover from
|
|
m_flNextPrimaryAttack = m_flNextSecondaryAttack += 0.5;
|
|
}
|
|
|
|
//
|
|
// Ammo Box
|
|
//
|
|
|
|
void CDesertEagleAmmo::Spawn()
|
|
{
|
|
Precache();
|
|
SET_MODEL(ENT(pev),"models/ammo_deagle.mdl");
|
|
CWasteAmmo::Spawn();
|
|
}
|
|
|
|
void CDesertEagleAmmo::Precache()
|
|
{
|
|
PRECACHE_MODEL("models/ammo_deagle.mdl");
|
|
}
|
|
|
|
BOOL CDesertEagleAmmo::AddAmmo(CBaseEntity *pOther)
|
|
{
|
|
if (pOther->GiveAmmo( AMMO_GIVE_DEAGLE,".50 AE",AMMO_MAX_DEAGLE ) != -1)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
/*************
|
|
Ruger .454
|
|
*************/
|
|
|
|
void CRuger::Spawn()
|
|
{
|
|
pev->classname = MAKE_STRING("weapon_ruger");
|
|
|
|
m_iBulletType = BULLET_454CASULL;
|
|
m_iId = WEAPON_RUGER;
|
|
m_iDefaultAmmo = AMMO_GIVE_RUGER;
|
|
m_iClipSize = CLIP_RUGER;
|
|
|
|
CSidearm::Spawn();
|
|
|
|
m_fAccuracy = 0.055;
|
|
m_fRateOfFire = 0.400;
|
|
m_iExtraRound = FALSE;
|
|
m_bInZoom = FALSE;
|
|
m_bStartZoom = FALSE;
|
|
|
|
// m_flTimeWeaponIdle = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
|
|
}
|
|
|
|
void CRuger::Precache()
|
|
{
|
|
PRECACHE_SOUND("weapons/ruger_fire.wav");
|
|
|
|
PRECACHE_MODEL("models/shells/shell_454_lo.mdl");
|
|
PRECACHE_MODEL("models/shells/shell_454_hi.mdl");
|
|
|
|
m_usFire1 = PRECACHE_EVENT(1,"events/ruger.sc");
|
|
|
|
CSidearm::Precache();
|
|
}
|
|
|
|
int CRuger::GetItemInfo(ItemInfo *p)
|
|
{
|
|
p->pszAmmo1 = ".454 Casull";
|
|
p->iMaxAmmo1 = AMMO_MAX_RUGER;
|
|
p->pszAmmo2 = NULL;
|
|
p->iMaxAmmo2 = -1;
|
|
p->iMaxClip = CLIP_RUGER;
|
|
|
|
p->iPosition = 3;
|
|
|
|
p->iId = m_iId = WEAPON_RUGER;
|
|
p->iWeight = WEIGHT_RUGER;
|
|
|
|
return CSidearm::GetItemInfo(p);
|
|
}
|
|
|
|
float CRuger::flGetTiltedDamage()
|
|
{
|
|
float fRet = RANDOM_FLOAT(50,60);
|
|
|
|
// 10% accuracy bonus when aiming or sniping
|
|
if(m_iState == SIDEARM_AIM || m_bInZoom)
|
|
fRet *= 1.10f;
|
|
|
|
return fRet;
|
|
}
|
|
|
|
const char *CRuger::szGetDeathNoticeString()
|
|
{
|
|
return RANDOM_LONG(0,1) ? DEATH_RUGER_1 : DEATH_RUGER_2;
|
|
}
|
|
|
|
void CRuger::PackWeapon(void *weapon_data)
|
|
{
|
|
CSidearm::PackWeapon(weapon_data);
|
|
|
|
// Save zoom
|
|
weapon_data_t *local_data = (weapon_data_t*)weapon_data;
|
|
local_data->m_fInZoom = m_bInZoom;
|
|
}
|
|
|
|
void CRuger::UnpackWeapon(void *weapon_data)
|
|
{
|
|
CSidearm::UnpackWeapon(weapon_data);
|
|
|
|
// Load zoom
|
|
weapon_data_t *local_data = (weapon_data_t*)weapon_data;
|
|
|
|
if(m_bInZoom != local_data->m_fInZoom)
|
|
{
|
|
m_bInZoom = local_data->m_fInZoom;
|
|
|
|
// somehow client was mixed up on zoom status, so fix
|
|
// the situation :(
|
|
if(m_bInZoom == TRUE)
|
|
{
|
|
MODIFY_PLAYER_SPEED(m_pPlayer,0.75);
|
|
|
|
ClientSway();
|
|
|
|
m_pPlayer->pev->fov = m_pPlayer->m_iFOV = 45;
|
|
}
|
|
else
|
|
{
|
|
MODIFY_PLAYER_SPEED(m_pPlayer,0);
|
|
|
|
#ifdef CLIENT_DLL
|
|
V_StopSway();
|
|
#endif
|
|
|
|
m_pPlayer->pev->fov = m_pPlayer->m_iFOV = 0;
|
|
m_bInZoom = FALSE;
|
|
|
|
m_iState = SIDEARM_SHOOT;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CRuger::SwingWeapon()
|
|
{
|
|
}
|
|
|
|
void CRuger::PistolFire(float spread,float rof)
|
|
{
|
|
if(m_iClip <= 0)
|
|
{
|
|
// if(m_fFireOnEmpty)
|
|
// {
|
|
SendWeaponAnim(RUGER_SHOOT_EMPTY,UseDecrement() ? 1 : 0);
|
|
PlayEmptySound();
|
|
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.3;
|
|
// }
|
|
return;
|
|
}
|
|
|
|
// Modify gun logic if we're aiming
|
|
if(m_iState == SIDEARM_AIM || m_bInZoom)
|
|
{
|
|
spread /= RUGER_AIMACC;
|
|
rof *= RUGER_AIMROF;
|
|
|
|
// If we are moving, incur an ADDITIONAL rof penalty
|
|
if(m_iId == WEAPON_DEAGLE)
|
|
{
|
|
// slooow
|
|
if(m_pPlayer->pev->velocity[0] != 0 || m_pPlayer->pev->velocity[1] != 0 || m_pPlayer->pev->velocity[2] != 0)
|
|
rof *= MOVING_AIMPENALTY * 4;
|
|
}
|
|
else
|
|
{
|
|
if(m_pPlayer->pev->velocity[0] != 0 || m_pPlayer->pev->velocity[1] != 0 || m_pPlayer->pev->velocity[2] != 0)
|
|
rof *= MOVING_AIMPENALTY;
|
|
}
|
|
}
|
|
|
|
#ifdef CLIENT_DLL
|
|
if(m_bInZoom)
|
|
{
|
|
// Refresh zoom sway
|
|
ClientSway();
|
|
}
|
|
#endif
|
|
|
|
m_iClip--;
|
|
m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH;
|
|
|
|
// player "shoot" animation
|
|
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
|
|
|
m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME;
|
|
m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;
|
|
|
|
Vector vecSrc = m_pPlayer->GetGunPosition( );
|
|
Vector vecAiming = gpGlobals->v_forward;
|
|
Vector dir;
|
|
|
|
// Accuracy modifiers
|
|
if(m_pPlayer->pev->flags & FL_DUCKING)
|
|
dir = m_pPlayer->FireBulletsPlayer(this, 1, vecSrc, vecAiming, Vector(spread*SIDEARM_DUCKPENALTY,spread*SIDEARM_DUCKPENALTY,spread*SIDEARM_DUCKPENALTY), 8192, m_iBulletType, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed, P_RUGER );
|
|
else if(m_pPlayer->pev->flags & FL_ONGROUND)
|
|
dir = m_pPlayer->FireBulletsPlayer(this, 1, vecSrc, vecAiming, Vector(spread,spread,spread), 8192, m_iBulletType, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed, P_RUGER );
|
|
else
|
|
dir = m_pPlayer->FireBulletsPlayer(this, 1, vecSrc, vecAiming, Vector(spread*SIDEARM_JUMPPENALTY,spread*SIDEARM_JUMPPENALTY,spread*SIDEARM_JUMPPENALTY), 8192, m_iBulletType, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed, P_RUGER );
|
|
|
|
int flags;
|
|
#if defined( CLIENT_WEAPONS )
|
|
flags = FEV_NOTHOST;
|
|
#else
|
|
flags = 0;
|
|
#endif
|
|
|
|
PLAYBACK_EVENT_FULL(flags,
|
|
m_pPlayer->edict(),
|
|
m_usFire1,
|
|
0.0,
|
|
(float*)&g_vecZero,
|
|
(float*)&g_vecZero,
|
|
dir.x,
|
|
dir.y,
|
|
0,
|
|
(m_bInZoom == 1) ? 1 : 0,
|
|
( m_iClip == 0 ) ? 1 : 0,
|
|
(m_iState == SIDEARM_AIM) ? 1 : 0 );
|
|
|
|
m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + rof;
|
|
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + RANDOM_FLOAT ( 10, 15 );
|
|
m_iAllowFire = FALSE;
|
|
}
|
|
|
|
void CRuger::SpecialMode()
|
|
{
|
|
if(m_pPlayer->m_flNextAttack > 0.0 )
|
|
return;
|
|
|
|
if( m_bInZoom )
|
|
{
|
|
MODIFY_PLAYER_SPEED(m_pPlayer,0);
|
|
|
|
#ifdef CLIENT_DLL
|
|
V_StopSway();
|
|
#endif
|
|
|
|
m_pPlayer->pev->fov = m_pPlayer->m_iFOV = 0;
|
|
m_bInZoom = FALSE;
|
|
|
|
m_pPlayer->m_flNextAttack = m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.75;
|
|
}
|
|
else
|
|
{
|
|
if(m_iState == SIDEARM_SHOOT)
|
|
SetState(SIDEARM_AIM);
|
|
else if(m_iState == SIDEARM_AIM)
|
|
SetState(SIDEARM_SHOOT);
|
|
}
|
|
}
|
|
|
|
void CRuger::ItemPostFrame()
|
|
{
|
|
CSidearm::ItemPostFrame();
|
|
|
|
if(m_bStartZoom && m_pPlayer->m_flNextAttack <= UTIL_WeaponTimeBase())
|
|
{
|
|
m_bStartZoom = FALSE;
|
|
SecondaryAttack();
|
|
}
|
|
}
|
|
|
|
void CRuger::SecondaryAttack()
|
|
{
|
|
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.45;
|
|
|
|
if(m_iState == SIDEARM_SHOOT)
|
|
{
|
|
SetState(SIDEARM_AIM);
|
|
m_bStartZoom = TRUE;
|
|
return;
|
|
}
|
|
|
|
if(m_pPlayer->pev->fov != 0)
|
|
{
|
|
MODIFY_PLAYER_SPEED(m_pPlayer,0);
|
|
|
|
#ifdef CLIENT_DLL
|
|
V_StopSway();
|
|
#endif
|
|
|
|
m_pPlayer->pev->fov = m_pPlayer->m_iFOV = 0;
|
|
m_bInZoom = FALSE;
|
|
|
|
SetState(SIDEARM_SHOOT);
|
|
}
|
|
else if(m_pPlayer->pev->fov != 45)
|
|
{
|
|
MODIFY_PLAYER_SPEED(m_pPlayer,0.5);
|
|
|
|
#ifdef CLIENT_DLL
|
|
ClientSway();
|
|
#endif
|
|
|
|
m_pPlayer->pev->fov = m_pPlayer->m_iFOV = 45;
|
|
m_bInZoom = TRUE;
|
|
}
|
|
}
|
|
|
|
void CRuger::SetState(int statenum)
|
|
{
|
|
m_iOldState = m_iState;
|
|
|
|
switch(statenum)
|
|
{
|
|
case SIDEARM_SHOOT:
|
|
if(m_iState == SIDEARM_AIM)
|
|
SendWeaponAnim(RUGER_END_AIM,UseDecrement() ? 1 : 0);
|
|
else
|
|
SendWeaponAnim(RUGER_IDLE,UseDecrement() ? 1 : 0);
|
|
m_iState = SIDEARM_SHOOT;
|
|
break;
|
|
case SIDEARM_AIM:
|
|
m_iState = SIDEARM_AIM;
|
|
SendWeaponAnim(RUGER_GOTO_AIM,UseDecrement() ? 1 : 0);
|
|
break;
|
|
}
|
|
|
|
m_pPlayer->m_flNextAttack = m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.75;
|
|
}
|
|
|
|
void CRuger::Reload()
|
|
{
|
|
if(m_bInZoom && m_iClip != m_iClipSize)
|
|
{
|
|
MODIFY_PLAYER_SPEED(m_pPlayer,0);
|
|
|
|
// Disable zoom for now.
|
|
m_pPlayer->pev->fov = m_pPlayer->m_iFOV = 0;
|
|
#ifdef CLIENT_DLL
|
|
V_StopSway();
|
|
#endif
|
|
// m_bInZoom = FALSE;
|
|
}
|
|
|
|
CSidearm::Reload();
|
|
}
|
|
|
|
BOOL CRuger::Deploy()
|
|
{
|
|
int ret = CSidearm::Deploy();
|
|
m_flTimeWeaponIdle = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 5, 7 );
|
|
return ret;
|
|
}
|
|
|
|
void CRuger::WeaponIdle()
|
|
{
|
|
CSidearm::WeaponIdle();
|
|
|
|
if (m_flTimeWeaponIdle >= UTIL_WeaponTimeBase())
|
|
return;
|
|
|
|
if(!m_bInZoom && m_iState != SIDEARM_AIM)
|
|
SendWeaponAnim( RUGER_IDLE2, UseDecrement() ? 1 : 0 );
|
|
|
|
m_flTimeWeaponIdle = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 5, 15 ); // how long till we do this again.
|
|
}
|
|
|
|
void CRuger::Holster(int skiplocal)
|
|
{
|
|
if(m_bInZoom)
|
|
{
|
|
m_pPlayer->pev->fov = m_pPlayer->m_iFOV = 0;
|
|
#ifdef CLIENT_DLL
|
|
V_StopSway();
|
|
#endif
|
|
}
|
|
|
|
m_bInZoom = FALSE;
|
|
CSidearm::Holster(skiplocal);
|
|
}
|
|
|
|
void CRuger::ClientSway()
|
|
{
|
|
#ifdef CLIENT_DLL
|
|
// Ducking
|
|
if(m_pPlayer->pev->flags & FL_DUCKING)
|
|
V_SetSway(1.75);
|
|
// On Ground
|
|
else if(m_pPlayer->pev->flags & FL_ONGROUND)
|
|
V_SetSway(3.25);
|
|
// Jumping
|
|
else
|
|
V_SetSway(6);
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// Ammo Box
|
|
//
|
|
void CRugerAmmo::Spawn()
|
|
{
|
|
Precache();
|
|
SET_MODEL(ENT(pev),"models/ammo_ruger.mdl");
|
|
CWasteAmmo::Spawn();
|
|
}
|
|
|
|
void CRugerAmmo::Precache()
|
|
{
|
|
PRECACHE_MODEL("models/ammo_ruger.mdl");
|
|
}
|
|
|
|
BOOL CRugerAmmo::AddAmmo(CBaseEntity *pOther)
|
|
{
|
|
if(pOther->GiveAmmo( AMMO_GIVE_RUGER,".454 Casull",AMMO_MAX_RUGER ) != -1)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
/*************
|
|
Handcannon
|
|
*************/
|
|
|
|
void CHandcannon::Spawn()
|
|
{
|
|
CWasteWeapon::Spawn();
|
|
Precache();
|
|
|
|
// Now work on the HC itself
|
|
pev->classname = MAKE_STRING("weapon_handcannon");
|
|
|
|
m_iBulletType = BULLET_556MM;
|
|
m_iId = WEAPON_HANDCANNON;
|
|
m_iDefaultAmmo = AMMO_GIVE_HANDCANNON;
|
|
m_iClipSize = CLIP_HANDCANNON;
|
|
|
|
m_fAccuracy = 0.0585;
|
|
m_fRateOfFire = 0.420;
|
|
|
|
m_bLaserVisible = FALSE;
|
|
|
|
SET_MODEL(ENT(pev),"models/w_handcannon.mdl");
|
|
|
|
FallInit();
|
|
}
|
|
|
|
void CHandcannon::Precache()
|
|
{
|
|
PRECACHE_MODEL("models/v_handcannon.mdl");
|
|
PRECACHE_MODEL("models/p_handcannon.mdl");
|
|
PRECACHE_MODEL("models/w_handcannon.mdl");
|
|
|
|
PRECACHE_MODEL("models/shells/shell_556mm_lo.mdl");
|
|
PRECACHE_MODEL("models/shells/shell_556mm_hi.mdl");
|
|
PRECACHE_MODEL("models/shells/mag_handcannon.mdl");
|
|
|
|
PRECACHE_MODEL("sprites/hand_laser_dot.spr");
|
|
|
|
PRECACHE_SOUND("weapons/handcannon_fire.wav");
|
|
PRECACHE_SOUND("weapons/handcannon_fire_empty.wav");
|
|
|
|
PRECACHE_SOUND("weapons/handcannon_laser_on.wav");
|
|
PRECACHE_SOUND("weapons/handcannon_laser_off.wav");
|
|
|
|
m_usFire1 = PRECACHE_EVENT(1,"events/handcannon.sc");
|
|
}
|
|
|
|
int CHandcannon::GetItemInfo(ItemInfo *p)
|
|
{
|
|
p->pszName = STRING(pev->classname);
|
|
p->iSlot = 1;
|
|
p->iFlags = 0;
|
|
|
|
p->pszAmmo1 = ".223 Handcannon";
|
|
p->iMaxAmmo1 = AMMO_MAX_HANDCANNON;
|
|
p->pszAmmo2 = NULL;
|
|
p->iMaxAmmo2 = -1;
|
|
p->iMaxClip = CLIP_HANDCANNON;
|
|
|
|
p->iPosition = 4;
|
|
|
|
p->iId = m_iId = WEAPON_HANDCANNON;
|
|
p->iWeight = WEIGHT_HANDCANNON;
|
|
|
|
return 1;
|
|
}
|
|
|
|
float CHandcannon::flGetTiltedDamage()
|
|
{
|
|
float fRet = RANDOM_FLOAT(65,75);
|
|
|
|
// 5% damage increase
|
|
if(m_bLaserVisible)
|
|
fRet *= 1.05f;
|
|
|
|
return fRet;
|
|
}
|
|
|
|
const char *CHandcannon::szGetDeathNoticeString()
|
|
{
|
|
return RANDOM_LONG(0,1) ? DEATH_HANDCANNON_1 : DEATH_HANDCANNON_2;
|
|
}
|
|
|
|
void CHandcannon::PackWeapon(void *weapon_data)
|
|
{
|
|
weapon_data_t *local_data = (weapon_data_t*)weapon_data;
|
|
|
|
local_data->m_iWeaponState = m_bLaserVisible;
|
|
local_data->fuser4 = m_iAllowFire;
|
|
local_data->iuser4 = (m_pPlayer->m_pActiveItem == this) ? 1 : 0; // Check for client predicted lasersight.
|
|
}
|
|
|
|
void CHandcannon::UnpackWeapon(void *weapon_data)
|
|
{
|
|
weapon_data_t *local_data = (weapon_data_t*)weapon_data;
|
|
|
|
m_bLaserVisible = local_data->m_iWeaponState;
|
|
m_iAllowFire = local_data->fuser4;
|
|
|
|
#ifdef CLIENT_DLL
|
|
if(local_data->iuser4)
|
|
g_iClientLasersEnabled[GetLocalPlayerIndex()] = m_bLaserVisible;
|
|
else
|
|
g_iClientLasersEnabled[GetLocalPlayerIndex()] = 0;
|
|
#endif
|
|
}
|
|
|
|
void CHandcannon::PrimaryAttack()
|
|
{
|
|
if(!m_iAllowFire)
|
|
return;
|
|
m_iAllowFire = FALSE;
|
|
|
|
if(m_iClip <= 0)
|
|
{
|
|
if(m_fFireOnEmpty)
|
|
{
|
|
PlayEmptySound();
|
|
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.3;
|
|
}
|
|
SendWeaponAnim(HC_SHOOT_EMPTY,UseDecrement() ? 1 : 0);
|
|
|
|
return;
|
|
}
|
|
|
|
// OMG kickback!
|
|
#ifndef CLIENT_DLL
|
|
float flZVel = m_pPlayer->pev->velocity.z;
|
|
|
|
m_pPlayer->pev->velocity = m_pPlayer->pev->velocity - gpGlobals->v_forward * 125;
|
|
|
|
// clamp the z velocity so people
|
|
// cant HC jump with the gun :)
|
|
m_pPlayer->pev->velocity.z = flZVel;
|
|
#endif
|
|
|
|
m_iClip--;
|
|
m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH;
|
|
|
|
// player "shoot" animation
|
|
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
|
|
|
m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME;
|
|
m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;
|
|
|
|
Vector vecSrc = m_pPlayer->GetGunPosition( );
|
|
Vector vecAiming = gpGlobals->v_forward;
|
|
Vector dir;
|
|
|
|
float spread = m_fAccuracy;
|
|
float rof = m_fRateOfFire;
|
|
|
|
if(m_bLaserVisible)
|
|
{
|
|
spread /= 2;
|
|
rof = 1.5f;
|
|
}
|
|
|
|
// Accuracy modifiers
|
|
if(m_pPlayer->pev->flags & FL_DUCKING)
|
|
dir = m_pPlayer->FireBulletsPlayer(this, 1, vecSrc, vecAiming, Vector(spread*HANDCANNON_DUCKPENALTY,spread*HANDCANNON_DUCKPENALTY,spread*HANDCANNON_DUCKPENALTY), 8192, m_iBulletType, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed, P_HANDCANNON );
|
|
else if(m_pPlayer->pev->flags & FL_ONGROUND)
|
|
dir = m_pPlayer->FireBulletsPlayer(this, 1, vecSrc, vecAiming, Vector(spread,spread,spread), 8192, m_iBulletType, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed, P_HANDCANNON );
|
|
else
|
|
dir = m_pPlayer->FireBulletsPlayer(this, 1, vecSrc, vecAiming, Vector(spread*HANDCANNON_JUMPPENALTY,spread*HANDCANNON_JUMPPENALTY,spread*HANDCANNON_JUMPPENALTY), 8192, m_iBulletType, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed, P_HANDCANNON );
|
|
|
|
int flags;
|
|
#if defined( CLIENT_WEAPONS )
|
|
flags = FEV_NOTHOST;
|
|
#else
|
|
flags = 0;
|
|
#endif
|
|
|
|
PLAYBACK_EVENT_FULL(flags,
|
|
m_pPlayer->edict(),
|
|
m_usFire1,
|
|
0.0,
|
|
(float*)&g_vecZero,
|
|
(float*)&g_vecZero,
|
|
dir.x,
|
|
dir.y,
|
|
0,
|
|
0,
|
|
(m_iClip == 0) ? 1 : 0,
|
|
m_bLaserVisible );
|
|
|
|
m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + rof;
|
|
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + RANDOM_FLOAT ( 10, 15 );
|
|
}
|
|
|
|
void CHandcannon::SecondaryAttack()
|
|
{
|
|
m_bLaserVisible = !m_bLaserVisible;
|
|
|
|
if(m_bLaserVisible)
|
|
{
|
|
// MODIFY_PLAYER_SPEED(m_pPlayer,0.85);
|
|
#ifdef CLIENT_DLL
|
|
g_iClientLasersEnabled[GetLocalPlayerIndex()] = 1;
|
|
CenterPrint("Lasersight on");
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// MODIFY_PLAYER_SPEED(m_pPlayer,1);
|
|
#ifdef CLIENT_DLL
|
|
g_iClientLasersEnabled[GetLocalPlayerIndex()] = 0;
|
|
CenterPrint("Lasersight off");
|
|
#endif
|
|
}
|
|
|
|
int flags;
|
|
#if defined( CLIENT_WEAPONS )
|
|
flags = FEV_NOTHOST;
|
|
#else
|
|
flags = 0;
|
|
#endif
|
|
|
|
PLAYBACK_EVENT_FULL(flags,
|
|
m_pPlayer->edict(),
|
|
m_usFire1,
|
|
0.0,
|
|
(float*)&g_vecZero,
|
|
(float*)&g_vecZero,
|
|
0.0,
|
|
0.0,
|
|
1, // laser activation sound
|
|
0,
|
|
0,
|
|
m_bLaserVisible ); // Which sound to play
|
|
|
|
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.45f;
|
|
}
|
|
|
|
void CHandcannon::ItemPostFrame()
|
|
{
|
|
if ((m_fInReload) && ( m_pPlayer->m_flNextAttack <= UTIL_WeaponTimeBase() ) )
|
|
{
|
|
// complete the reload.
|
|
int j = Q_min( iMaxClip(), m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]);
|
|
|
|
m_iClip = 0;
|
|
|
|
// Add them to the clip
|
|
m_iClip += j;
|
|
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= j;
|
|
|
|
#ifndef CLIENT_DLL
|
|
m_pPlayer->TabulateAmmo();
|
|
#endif
|
|
m_fInReload = FALSE;
|
|
}
|
|
|
|
CWasteWeapon::ItemPostFrame();
|
|
|
|
// Set allow fire mode
|
|
if(!(m_pPlayer->pev->button & IN_ATTACK))
|
|
m_iAllowFire = TRUE;
|
|
// else
|
|
// m_iAllowFire = FALSE;
|
|
}
|
|
|
|
void CHandcannon::Reload()
|
|
{
|
|
if(m_flNextPrimaryAttack > UTIL_WeaponTimeBase() || m_flNextSecondaryAttack > UTIL_WeaponTimeBase())
|
|
return;
|
|
|
|
int iResult;
|
|
|
|
// See if we need to reload
|
|
if(m_iClip == m_iClipSize)
|
|
return;
|
|
|
|
// player "reload" animation
|
|
m_pPlayer->SetAnimation( PLAYER_RELOAD );
|
|
|
|
if (m_iClip == 0)
|
|
iResult = DefaultReload( m_iClipSize, HC_RELOAD_EMPTY, 3.0f );
|
|
else
|
|
iResult = DefaultReload( m_iClipSize, HC_RELOAD, 2.75f );
|
|
|
|
if (iResult)
|
|
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + RANDOM_FLOAT ( 10, 15 );
|
|
}
|
|
|
|
BOOL CHandcannon::Deploy()
|
|
{
|
|
if(!m_iClip)
|
|
{
|
|
if(!DefaultDeploy("models/v_handcannon.mdl","models/p_handcannon.mdl",HC_DRAW_EMPTY,"HC"))
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
if(!DefaultDeploy("models/v_handcannon.mdl","models/p_handcannon.mdl",HC_DRAW,"HC"))
|
|
return FALSE;
|
|
}
|
|
|
|
#ifdef CLIENT_DLL
|
|
g_iClientLasersEnabled[GetLocalPlayerIndex()] = m_bLaserVisible;
|
|
#endif
|
|
|
|
return CWasteWeapon::Deploy();
|
|
}
|
|
|
|
BOOL CHandcannon::PlayEmptySound()
|
|
{
|
|
if (m_iPlayEmptySound)
|
|
{
|
|
m_iPlayEmptySound = 0;
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void CHandcannon::WeaponIdle()
|
|
{
|
|
ResetEmptySound();
|
|
}
|
|
|
|
void CHandcannon::Holster(int skiplocal)
|
|
{
|
|
// m_bLaserVisible = FALSE;
|
|
|
|
#ifdef CLIENT_DLL
|
|
g_iClientLasersEnabled[GetLocalPlayerIndex()] = 0;
|
|
#endif
|
|
CWasteWeapon::Holster(skiplocal);
|
|
}
|
|
|
|
BOOL CHandcannon::bLaserActive()
|
|
{
|
|
if( m_pPlayer != NULL && m_pPlayer->m_pActiveItem == this )
|
|
return m_bLaserVisible;
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Ammo Box
|
|
//
|
|
void CHandcannonAmmo::Spawn()
|
|
{
|
|
Precache();
|
|
SET_MODEL(ENT(pev),"models/ammo_handcannon.mdl");
|
|
CWasteAmmo::Spawn();
|
|
}
|
|
|
|
void CHandcannonAmmo::Precache()
|
|
{
|
|
PRECACHE_MODEL("models/ammo_handcannon.mdl");
|
|
}
|
|
|
|
BOOL CHandcannonAmmo::AddAmmo(CBaseEntity *pOther)
|
|
{
|
|
if(pOther->GiveAmmo( AMMO_GIVE_HANDCANNON, ".223 Handcannon", AMMO_MAX_HANDCANNON) != -1)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|