/*** * * 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(ammo_buckshot,CShotgunAmmo); LINK_ENTITY_TO_CLASS(ammo_winchester,CWinchesterAmmo); LINK_ENTITY_TO_CLASS(ammo_jackhammer,CJackHammerAmmo); LINK_ENTITY_TO_CLASS(weapon_sawedoff,CSawedOff); LINK_ENTITY_TO_CLASS(weapon_mossberg,CMossberg); LINK_ENTITY_TO_CLASS(weapon_winchester,CWinchester); LINK_ENTITY_TO_CLASS(weapon_jackhammer,CJackHammer); #define SHOTGUN_SHOOT_STATE 1 #define SHOTGUN_RELOAD_STATE 2 enum reload_state_e { RELOAD_NONE, RELOAD_START, RELOAD_END, }; /************* Shotgun *************/ int CShotgun::GetItemInfo(ItemInfo *p) { p->pszName = STRING(pev->classname); p->iSlot = 2; p->iFlags = 0; p->pszAmmo1 = "Buckshot"; p->iMaxAmmo1 = AMMO_MAX_BUCKSHOT; p->pszAmmo2 = NULL; p->iMaxAmmo2 = -1; return 1; } void CShotgun::ItemPostFrame() { if ((m_fInReload) && ( m_pPlayer->m_flNextAttack <= UTIL_WeaponTimeBase() ) ) { // complete the reload. int j = min( 1, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]); // 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; // Handle reloads if needed //#ifndef CLIENT_DLL if(m_iState == SHOTGUN_RELOAD_STATE && m_flNextPrimaryAttack <= UTIL_WeaponTimeBase()) { switch(m_iReloadState) { case RELOAD_START: Reload(); // User must hold down button to reload. if(!(m_pPlayer->pev->button & IN_ATTACK)) m_iReloadState = RELOAD_END; break; case RELOAD_END: Reload(); break; } } //#endif } void CShotgun::WeaponIdle() { ResetEmptySound(); } void CShotgun::PackWeapon(void *weapon_data) { weapon_data_t *local_data = (weapon_data_t*)weapon_data; local_data->m_iWeaponState = m_iState; } void CShotgun::UnpackWeapon(void *weapon_data) { #ifdef CLIENT_DLL weapon_data_t *local_data = (weapon_data_t*)weapon_data; m_iState = local_data->m_iWeaponState; #endif } // // Ammo Box // void CShotgunAmmo::Spawn() { Precache(); SET_MODEL(ENT(pev),"models/ammo_buckshot.mdl"); CWasteAmmo::Spawn(); } void CShotgunAmmo::Precache() { PRECACHE_MODEL("models/ammo_buckshot.mdl"); } BOOL CShotgunAmmo::AddAmmo(CBaseEntity *pOther) { if(pOther->GiveAmmo( AMMO_GIVE_BUCKSHOT, "Buckshot", AMMO_MAX_BUCKSHOT) != -1) return TRUE; return FALSE; } /************* Mossberg 12 Gauge *************/ void CMossberg::Spawn() { Precache(); pev->classname = MAKE_STRING("weapon_mossberg"); m_iBulletType = BULLET_12GAUGE; m_iId = WEAPON_MOSSBERG; m_iDefaultAmmo = AMMO_GIVE_BUCKSHOT; m_iClipSize = CLIP_MOSSBERG; m_iAllowFire = TRUE; m_iState = SHOTGUN_SHOOT_STATE; m_iReloadState = RELOAD_NONE; SET_MODEL(ENT(pev),"models/w_mossberg.mdl"); FallInit(); } void CMossberg::Precache() { PRECACHE_MODEL("models/v_mossberg.mdl"); PRECACHE_MODEL("models/p_mossberg.mdl"); PRECACHE_MODEL("models/w_mossberg.mdl"); PRECACHE_MODEL("models/shells/shell_buckshot_lo.mdl"); PRECACHE_MODEL("models/shells/shell_buckshot_hi.mdl"); PRECACHE_SOUND("weapons/mossberg_draw.wav"); PRECACHE_SOUND("weapons/mossberg_fire_empty.wav"); PRECACHE_SOUND("weapons/mossberg_fire1.wav"); PRECACHE_SOUND("weapons/mossberg_fire2.wav"); PRECACHE_SOUND("weapons/mossberg_holster.wav"); PRECACHE_SOUND("weapons/mossberg_pump.wav"); PRECACHE_SOUND("weapons/mossberg_reload.wav"); m_usFire1 = PRECACHE_EVENT(1,"events/mossberg.sc"); } int CMossberg::GetItemInfo(ItemInfo *p) { p->iMaxClip = CLIP_MOSSBERG; p->iPosition = 0; p->iId = m_iId = WEAPON_MOSSBERG; p->iWeight = WEIGHT_MOSSBERG; return CShotgun::GetItemInfo(p); } float CMossberg::flGetTiltedDamage() { return RANDOM_FLOAT(14,19); } char *CMossberg::szGetDeathNoticeString() { return RANDOM_LONG(0,1) ? DEATH_MOSSBERG_1 : DEATH_MOSSBERG_2; } void CMossberg::PrimaryAttack() { if(!m_iAllowFire || m_iState == SHOTGUN_RELOAD_STATE) return; // don't fire underwater if (m_pPlayer->pev->waterlevel == 3) { PlayEmptySound( ); m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15; return; } if(!m_iClip) { PlayEmptySound(); SendWeaponAnim(MOSSBERG_SHOOT_EMPTY,UseDecrement() ? 1 : 0); m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.3; return; } int random_long = UTIL_SharedRandomLong(m_pPlayer->random_seed,0,1); m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME; m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH; m_iClip--; m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH; Vector vecSrc = m_pPlayer->GetGunPosition( ); Vector vecAiming = gpGlobals->v_forward; Vector vecDir; Vector vecSpread = Vector(MOSSBERG_SPREAD,MOSSBERG_SPREAD,MOSSBERG_SPREAD); vecDir = m_pPlayer->FireBulletsPlayer(this,MOSSBERG_SHOTCOUNT, vecSrc, vecAiming, vecSpread, 1280, m_iBulletType, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed ); 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, MOSSBERG_SPREAD, MOSSBERG_SPREAD, MOSSBERG_SHOTCOUNT*2, 1, // Shotgun blast 0, random_long); m_iAllowFire = FALSE; m_flTimeWeaponIdle = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 2, 4 ); // how long till we do this again. m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.75f; } void CMossberg::SecondaryAttack() { if(!m_iAllowFire || m_iState == SHOTGUN_RELOAD_STATE) return; // player "shoot" animation m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); #ifndef CLIENT_DLL // 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 ); 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, MOSSBERG_DMG_WHIP , 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; } // Kickback from stock if( pEntity->IsPlayer() ) { float flZVel = pEntity->pev->velocity.z; pEntity->pev->velocity = pEntity->pev->velocity + gpGlobals->v_forward * 225.0f; pEntity->pev->velocity.z = flZVel; } } #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, 0, 0, // Stock whip 0, 0); m_flTimeWeaponIdle = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 5, 9 ); // how long till we do this again. m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.25; } void CMossberg::Reload() { if(m_flNextPrimaryAttack > UTIL_WeaponTimeBase() || m_flNextSecondaryAttack > UTIL_WeaponTimeBase()) return; if(m_iState != SHOTGUN_RELOAD_STATE && (m_iClip == m_iClipSize || m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)) return; if(m_iState != SHOTGUN_RELOAD_STATE) { m_iState = SHOTGUN_RELOAD_STATE; m_iReloadState = RELOAD_NONE; } // if we're full, just go to the end. if(m_iClipSize == m_iClip) m_iReloadState = RELOAD_END; switch(m_iReloadState) { case RELOAD_NONE: SendWeaponAnim( MOSSBERG_GOTO_RELOAD, UseDecrement() ? 1 : 0 ); m_iReloadState = RELOAD_START; m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.6; break; case RELOAD_START: if(DefaultReload( m_iClipSize,MOSSBERG_RELOAD, 0.45 )) { m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.565; EMIT_SOUND(ENT(m_pPlayer->pev),CHAN_WEAPON,"weapons/mossberg_reload.wav",0.8,ATTN_NORM); break; } case RELOAD_END: m_iState = SHOTGUN_SHOOT_STATE; m_iReloadState = RELOAD_NONE; m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.825; SendWeaponAnim( MOSSBERG_END_RELOAD, UseDecrement() ? 1 : 0 ); m_flTimeWeaponIdle = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 4,5 ); // how long till we do this again.break; break; } } BOOL CMossberg::Deploy() { if(!DefaultDeploy("models/v_mossberg.mdl","models/p_mossberg.mdl",MOSSBERG_DRAW,"mossberg")) return FALSE; return CShotgun::Deploy(); } BOOL CMossberg::PlayEmptySound() { if (m_iPlayEmptySound) { m_iPlayEmptySound = 0; return 0; } return 0; } void CMossberg::WeaponIdle() { CShotgun::WeaponIdle(); if ( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() || m_iState != SHOTGUN_SHOOT_STATE) return; SendWeaponAnim( (RANDOM_LONG(0,1) == 0)? MOSSBERG_IDLE2 : MOSSBERG_IDLE3, UseDecrement() ? 1 : 0 ); m_flTimeWeaponIdle = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 5, 9 ); // how long till we do this again. } void CMossberg::Holster(int skiplocal) { CShotgun::Holster(skiplocal); } /************* Winchester *************/ void CWinchester::Spawn() { Precache(); pev->classname = MAKE_STRING("weapon_winchester"); m_iBulletType = BULLET_SLUG; m_iId = WEAPON_WINCHESTER; m_iDefaultAmmo = AMMO_GIVE_BUCKSHOT; m_iClipSize = CLIP_WINCHESTER; m_iState = SHOTGUN_SHOOT_STATE; m_iReloadState = RELOAD_NONE; SET_MODEL(ENT(pev),"models/w_winchester.mdl"); FallInit(); } void CWinchester::Precache() { PRECACHE_MODEL("models/v_winchester.mdl"); PRECACHE_MODEL("models/p_winchester.mdl"); PRECACHE_MODEL("models/w_winchester.mdl"); PRECACHE_MODEL("models/shells/shell_slug_lo.mdl"); PRECACHE_MODEL("models/shells/shell_slug_hi.mdl"); PRECACHE_SOUND("weapons/winchester_draw.wav"); PRECACHE_SOUND("weapons/winchester_fire_empty.wav"); PRECACHE_SOUND("weapons/winchester_fire1.wav"); PRECACHE_SOUND("weapons/winchester_fire2.wav"); PRECACHE_SOUND("weapons/winchester_pump.wav"); PRECACHE_SOUND("weapons/winchester_reload.wav"); m_usFire1 = PRECACHE_EVENT(1,"events/winchester.sc"); } int CWinchester::GetItemInfo(ItemInfo *p) { p->iMaxClip = CLIP_WINCHESTER; p->iPosition = 1; p->iId = m_iId = WEAPON_WINCHESTER; p->iWeight = WEIGHT_WINCHESTER; p->pszName = STRING(pev->classname); p->iSlot = 2; p->iFlags = 0; p->pszAmmo1 = "WinchesterAmmo"; p->iMaxAmmo1 = AMMO_MAX_WINCHESTER; p->pszAmmo2 = NULL; p->iMaxAmmo2 = -1; return 1; } float CWinchester::flGetTiltedDamage() { return RANDOM_FLOAT(75,85); } char *CWinchester::szGetDeathNoticeString() { return RANDOM_LONG(0,1) ? DEATH_WINCHESTER_1 : DEATH_WINCHESTER_2; } void CWinchester::PrimaryAttack() { if(!m_iAllowFire || m_iState == SHOTGUN_RELOAD_STATE) return; // don't fire underwater if (m_pPlayer->pev->waterlevel == 3) { PlayEmptySound( ); m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15; return; } if(!m_iClip) { PlayEmptySound(); // SendWeaponAnim(WINNY_SHOOT_EMPTY,UseDecrement() ? 1 : 0); m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.3; return; } int iAnimations = UTIL_SharedRandomLong(m_pPlayer->random_seed,0,1); m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.0f; m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME; m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH; m_iClip--; m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH; Vector vecSrc = m_pPlayer->GetGunPosition( ); Vector vecAiming = gpGlobals->v_forward; Vector vecDir; Vector vecSpread = Vector(WINCHESTER_SPREAD,WINCHESTER_SPREAD,WINCHESTER_SPREAD); vecDir = m_pPlayer->FireBulletsPlayer(this,1, vecSrc, vecAiming, vecSpread, 8192, m_iBulletType, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed, P_WINCHESTER ); 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, vecDir.x, vecDir.y, iAnimations, 0, 0, 0); m_iAllowFire = FALSE; m_flTimeWeaponIdle = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 2, 4 ); // how long till we do this again. } void CWinchester::SecondaryAttack() { } void CWinchester::Reload() { if(m_flNextPrimaryAttack > UTIL_WeaponTimeBase() || m_flNextSecondaryAttack > UTIL_WeaponTimeBase()) return; if(m_iState != SHOTGUN_RELOAD_STATE && (m_iClip == m_iClipSize || m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)) return; if(m_iState != SHOTGUN_RELOAD_STATE) { m_iState = SHOTGUN_RELOAD_STATE; m_iReloadState = RELOAD_NONE; } // if we're full, just go to the end. if(m_iClipSize == m_iClip) m_iReloadState = RELOAD_END; switch(m_iReloadState) { case RELOAD_NONE: SendWeaponAnim( WINNY_RELOAD_START, UseDecrement() ? 1 : 0 ); m_iReloadState = RELOAD_START; m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.7; break; case RELOAD_START: if(DefaultReload( m_iClipSize,WINNY_RELOAD_MIDDLE, 0.525 )) { m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.525; EMIT_SOUND(ENT(m_pPlayer->pev),CHAN_WEAPON,"weapons/winchester_reload.wav",0.8,ATTN_NORM); break; } case RELOAD_END: m_iState = SHOTGUN_SHOOT_STATE; m_iReloadState = RELOAD_NONE; m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.825; SendWeaponAnim( WINNY_RELOAD_END, UseDecrement() ? 1 : 0 ); m_flTimeWeaponIdle = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 4,5 ); // how long till we do this again.break; break; } } BOOL CWinchester::Deploy() { if(!DefaultDeploy("models/v_winchester.mdl","models/p_winchester.mdl",WINNY_DRAW,"winchester")) return FALSE; return CShotgun::Deploy(); } BOOL CWinchester::PlayEmptySound() { if (m_iPlayEmptySound) { m_iPlayEmptySound = 0; return 0; } return 0; } // // Ammo Box // void CWinchesterAmmo::Spawn() { Precache(); SET_MODEL(ENT(pev),"models/ammo_winchester.mdl"); CWasteAmmo::Spawn(); } void CWinchesterAmmo::Precache() { PRECACHE_MODEL("models/ammo_winchester.mdl"); } BOOL CWinchesterAmmo::AddAmmo(CBaseEntity *pOther) { if(pOther->GiveAmmo( AMMO_GIVE_WINCHESTER, "WinchesterAmmo", AMMO_MAX_WINCHESTER) != -1) return TRUE; return FALSE; } /************* Sawed Off Shotgun (Mad Max Babey!) *************/ void CSawedOff::Spawn() { Precache(); pev->classname = MAKE_STRING("weapon_sawedoff"); m_iBulletType = BULLET_20GAUGE; m_iId = WEAPON_SAWEDOFF; m_iDefaultAmmo = AMMO_GIVE_BUCKSHOT; m_iClipSize = CLIP_SAWEDOFF; m_iAllowFire = TRUE; SET_MODEL(ENT(pev),"models/w_sawedoff.mdl"); FallInit(); } void CSawedOff::Precache() { PRECACHE_MODEL("models/v_sawedoff.mdl"); PRECACHE_MODEL("models/p_sawedoff.mdl"); PRECACHE_MODEL("models/w_sawedoff.mdl"); PRECACHE_MODEL("models/shells/shell_buckshot_lo.mdl"); PRECACHE_MODEL("models/shells/shell_buckshot_hi.mdl"); PRECACHE_SOUND("weapons/sawedoff_draw.wav"); PRECACHE_SOUND("weapons/sawedoff_fire1.wav"); PRECACHE_SOUND("weapons/sawedoff_fire2.wav"); PRECACHE_SOUND("weapons/sawedoff_fire_empty.wav"); PRECACHE_SOUND("weapons/sawedoff_reload1.wav"); m_usFire1 = PRECACHE_EVENT(1,"events/sawedoff.sc"); } int CSawedOff::GetItemInfo(ItemInfo *p) { p->pszName = STRING(pev->classname); p->iSlot = 1; p->iFlags = 0; p->pszAmmo1 = "Buckshot"; p->iMaxAmmo1 = AMMO_MAX_BUCKSHOT; p->pszAmmo2 = NULL; p->iMaxAmmo2 = -1; p->iMaxClip = CLIP_SAWEDOFF; p->iPosition = 5; p->iId = m_iId = WEAPON_SAWEDOFF; p->iWeight = WEIGHT_SAWEDOFF; return 1; } float CSawedOff::flGetTiltedDamage() { return RANDOM_FLOAT( 16, 19 ); } char *CSawedOff::szGetDeathNoticeString() { return RANDOM_LONG(0,1) ? DEATH_SAWEDOFF_1 : DEATH_SAWEDOFF_2; } void CSawedOff::ItemPostFrame() { CWasteWeapon::ItemPostFrame(); // Set allow fire mode if(!(m_pPlayer->pev->button & IN_ATTACK)) m_iAllowFire = TRUE; } void CSawedOff::FireShotgun(int barrels) { if(!m_iAllowFire) return; // don't fire underwater if (m_pPlayer->pev->waterlevel == 3) { PlayEmptySound( ); m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15; return; } if(!m_iClip) { SendWeaponAnim(SAWED_SHOOT_EMPTY,UseDecrement() ? 1 : 0); PlayEmptySound(); m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.3; return; } else if(barrels == 2 && m_iClip == 1) { // If we dont have enough to go all out, // settle for second best. :) FireShotgun(1); return; } m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME; m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH; if(barrels == 2) m_iClip -= 2; else m_iClip--; // OMG kickback! #ifndef CLIENT_DLL float flZVel = m_pPlayer->pev->velocity.z; float kickback = (barrels == 1) ? 175 : 262.5; m_pPlayer->pev->velocity = m_pPlayer->pev->velocity - gpGlobals->v_forward * kickback; // clamp the z velocity so people // cant sawnoff jump with the gun :) m_pPlayer->pev->velocity.z = flZVel; #endif int flags; #if defined( CLIENT_WEAPONS ) flags = FEV_NOTHOST; #else flags = 0; #endif m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH; Vector vecSrc = m_pPlayer->GetGunPosition( ); Vector vecAiming = gpGlobals->v_forward; Vector vecDir; int shotCount = (barrels == 1) ? 7 : 12; float spread = (barrels == 1) ? 0.13 : 0.18; Vector vecSpread = Vector(spread,spread,spread); vecDir = m_pPlayer->FireBulletsPlayer(this, shotCount, vecSrc, vecAiming, vecSpread, 1280, m_iBulletType, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed ); PLAYBACK_EVENT_FULL(flags, m_pPlayer->edict(), m_usFire1, 0.0, (float*)&g_vecZero, (float*)&g_vecZero, spread, spread, barrels, 0, 0, 0); m_iAllowFire = FALSE; } void CSawedOff::PrimaryAttack() { FireShotgun(1); m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.20; } void CSawedOff::SecondaryAttack() { FireShotgun(2); m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.50; } void CSawedOff::Reload() { if(m_flNextPrimaryAttack > 0.0 || m_flNextSecondaryAttack > 0.0) return; int iResult; // See if we need to reload if(m_iClip == m_iClipSize) return; // player "reload" animation m_pPlayer->SetAnimation( PLAYER_RELOAD ); iResult = DefaultReload( m_iClipSize, SAWED_RELOAD, 1.6f ); if(iResult) { m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1.6f; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + RANDOM_FLOAT ( 10, 15 ); } } BOOL CSawedOff::Deploy() { if(!DefaultDeploy("models/v_sawedoff.mdl","models/p_sawedoff.mdl",SAWED_DRAW,"sawedoff")) return FALSE; return CWasteWeapon::Deploy(); } BOOL CSawedOff::PlayEmptySound() { if (m_iPlayEmptySound) { m_iPlayEmptySound = 0; return 0; } return 0; } /************* Pancor Jackhammer *************/ void CJackHammer::Spawn() { Precache(); pev->classname = MAKE_STRING("weapon_jackhammer"); m_iId = WEAPON_JACKHAMMER; m_iDefaultAmmo = AMMO_GIVE_JACKHAMMER; m_iClipSize = CLIP_JACKHAMMER; SET_MODEL(ENT(pev),"models/w_jackhammer.mdl"); FallInit(); } void CJackHammer::Precache() { PRECACHE_MODEL("models/v_jackhammer.mdl"); PRECACHE_MODEL("models/p_jackhammer.mdl"); PRECACHE_MODEL("models/w_jackhammer.mdl"); PRECACHE_MODEL("models/shells/shell_buckshot_lo.mdl"); PRECACHE_MODEL("models/shells/shell_buckshot_hi.mdl"); PRECACHE_SOUND("weapons/jackhammer_fire1.wav"); PRECACHE_SOUND("weapons/jackhammer_fire2.wav"); m_usFire1 = PRECACHE_EVENT(1,"events/jackhammer.sc"); } int CJackHammer::GetItemInfo(ItemInfo *p) { p->pszName = STRING(pev->classname); p->iSlot = 3; p->iFlags = 0; p->pszAmmo1 = "JackhammerAmmo"; p->iMaxAmmo1 = AMMO_MAX_JACKHAMMER; p->pszAmmo2 = NULL; p->iMaxAmmo2 = -1; p->iMaxClip = CLIP_JACKHAMMER; p->iPosition = iItemSlot() - 1; p->iId = m_iId = WEAPON_JACKHAMMER; p->iWeight = WEIGHT_UNIQUE; return 1; } float CJackHammer::flGetTiltedDamage() { return RANDOM_LONG(14,19); } char *CJackHammer::szGetDeathNoticeString() { return RANDOM_LONG(0,1) ? DEATH_JACKHAMMER_1 : DEATH_JACKHAMMER_2; } void CJackHammer::PrimaryAttack() { // don't fire underwater if (m_pPlayer->pev->waterlevel == 3) { PlayEmptySound( ); m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.15; return; } if(!m_iClip) { // SendWeaponAnim(SAWED_SHOOT_EMPTY,UseDecrement() ? 1 : 0); PlayEmptySound(); m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.10; return; } m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME; m_pPlayer->m_iWeaponFlash = BRIGHT_GUN_FLASH; m_iClip--; HALT_PLAYER(m_pPlayer,25,-1); int flags; #if defined( CLIENT_WEAPONS ) flags = FEV_NOTHOST; #else flags = 0; #endif m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH; Vector vecSrc = m_pPlayer->GetGunPosition( ); Vector vecAiming = gpGlobals->v_forward; Vector vecDir; float spread = MOSSBERG_SPREAD; Vector vecSpread = Vector(spread,spread,spread); vecDir = m_pPlayer->FireBulletsPlayer(this,MOSSBERG_SHOTCOUNT, vecSrc, vecAiming, vecSpread, 1280, BULLET_10GAUGE, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed ); PLAYBACK_EVENT_FULL(flags, m_pPlayer->edict(), m_usFire1, 0.0, (float*)&g_vecZero, (float*)&g_vecZero, spread, spread, MOSSBERG_SHOTCOUNT, (m_pPlayer->pev->flags & FL_DUCKING), // is the player ducking or not 0, 0); m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.13; } void CJackHammer::SecondaryAttack() { } void CJackHammer::Reload() { if(m_flNextPrimaryAttack > 0.0 || m_flNextSecondaryAttack > 0.0) return; // See if we need to reload if(m_iClip == m_iClipSize) return; // player "reload" animation m_pPlayer->SetAnimation( PLAYER_RELOAD ); int iResult = DefaultReload( m_iClipSize, JACKHAMMER_RELOAD, 3.34f ); } BOOL CJackHammer::Deploy() { if(!DefaultDeploy("models/v_jackhammer.mdl","models/p_jackhammer.mdl",JACKHAMMER_DRAW,"jackhammer")) return FALSE; return CWasteWeapon::Deploy(); } BOOL CJackHammer::PlayEmptySound() { if (m_iPlayEmptySound) { m_iPlayEmptySound = 0; return 0; } return 0; } // // Ammo Box // void CJackHammerAmmo::Spawn() { Precache(); SET_MODEL(ENT(pev),"models/ammo_jackhammer.mdl"); CWasteAmmo::Spawn(); } void CJackHammerAmmo::Precache() { PRECACHE_MODEL("models/ammo_jackhammer.mdl"); } BOOL CJackHammerAmmo::AddAmmo(CBaseEntity *pOther) { if(pOther->GiveAmmo( AMMO_GIVE_JACKHAMMER, "JackhammerAmmo", AMMO_MAX_JACKHAMMER) != -1) return TRUE; return FALSE; }