/*** * * 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; }