hlsdk-xash3d/dlls/hornetgun.cpp

1105 lines
32 KiB
C++

/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* 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
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD )
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "player.h"
#include "hornet.h"
#include "gamerules.h"
#include "effects.h"
#include "BMOD_messaging.h"
#include "decals.h"
#include "BMOD_zapgunrift.h"
#include "shake.h"
#include "squeakgrenade.h"
short iBSquidSpitSprite;
extern cvar_t bm_freezetime;
extern cvar_t bm_hornet_mod;
enum hgun_e
{
HGUN_IDLE1 = 0,
HGUN_FIDGETSWAY,
HGUN_FIDGETSHAKE,
HGUN_DOWN,
HGUN_UP,
HGUN_SHOOT
};
enum hgun_phase
{
HGUN_IDLE = 0,
HGUN_CHARGE,
HGUN_ZAP,
HGUN_ZAP_DONE,
HGUN_SPIT
};
enum firemode_e
{
FIREMODE_TRACK = 0,
FIREMODE_FAST
};
//=========================================================
// Bullsquid's spit projectile
//=========================================================
class BMODSquidSpit : public CBaseEntity
{
public:
void Spawn( void );
static void Shoot( entvars_t *Owner, Vector vecStart, Vector vecVelocity );
void Touch( CBaseEntity *pOther );
void EXPORT Animate( void );
static TYPEDESCRIPTION m_SaveData[];
int m_maxFrame;
entvars_t *pevOwner;
};
LINK_ENTITY_TO_CLASS( squidspit, BMODSquidSpit );
void BMODSquidSpit:: Spawn( void )
{
pev->movetype = MOVETYPE_FLY;
pev->classname = MAKE_STRING( "squidspit" );
pev->solid = SOLID_BBOX;
pev->rendermode = kRenderTransAlpha;
pev->renderamt = 255;
SET_MODEL( ENT( pev ), "sprites/bigspit.spr" );
pev->frame = 0;
pev->scale = 0.5;
UTIL_SetSize( pev, Vector( -4, -4, -4 ), Vector( 4, 4, 4 ) );
m_maxFrame = (float)MODEL_FRAMES( pev->modelindex ) - 1;
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
WRITE_BYTE( TE_BEAMFOLLOW );
WRITE_SHORT( entindex() ); // entity
WRITE_SHORT( g_sModelIndexLightning ); // model
WRITE_BYTE( 2 ); // life
WRITE_BYTE( 4 ); // width
WRITE_BYTE( 128 ); // r, g, b
WRITE_BYTE( 200 ); // r, g, b
WRITE_BYTE( 0 ); // r, g, b
WRITE_BYTE( 255 ); // brightness
MESSAGE_END(); // move PHS/PVS data sending into here (SEND_ALL, SEND_PVS, SEND_PHS)
}
void BMODSquidSpit::Animate( void )
{
pev->nextthink = gpGlobals->time + 0.1;
if( pev->frame++ )
{
if( pev->frame > m_maxFrame )
{
pev->frame = 0;
}
}
}
void BMODSquidSpit::Shoot( entvars_t *Owner, Vector vecStart, Vector vecVelocity )
{
BMODSquidSpit *pSpit = GetClassPtr( (BMODSquidSpit *)NULL );
pSpit->Spawn();
UTIL_SetOrigin( pSpit->pev, vecStart );
pSpit->pev->velocity = vecVelocity;
pSpit->pev->owner = ENT( Owner );
pSpit->pevOwner = Owner;
pSpit->SetThink( &BMODSquidSpit::Animate );
pSpit->pev->nextthink = gpGlobals->time + 0.1;
}
void BMODSquidSpit::Touch( CBaseEntity *pOther )
{
TraceResult tr;
int iPitch;
// splat sound
iPitch = RANDOM_FLOAT( 90, 110 );
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, "bullchicken/bc_acid1.wav", 1, ATTN_NORM, 0, iPitch );
switch( RANDOM_LONG( 0, 1 ) )
{
case 0:
EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, "bullchicken/bc_spithit1.wav", 1, ATTN_NORM, 0, iPitch );
break;
case 1:
EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, "bullchicken/bc_spithit2.wav", 1, ATTN_NORM, 0, iPitch );
break;
}
// make a splat on the wall
UTIL_TraceLine( pev->origin, pev->origin + pev->velocity, dont_ignore_monsters, ENT( pev ), &tr );
UTIL_DecalTrace( &tr, DECAL_SPIT1 + RANDOM_LONG( 0, 1 ) );
// make some flecks
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, tr.vecEndPos );
WRITE_BYTE( TE_SPRITE_SPRAY );
WRITE_COORD( tr.vecEndPos.x ); // pos
WRITE_COORD( tr.vecEndPos.y );
WRITE_COORD( tr.vecEndPos.z );
WRITE_COORD( tr.vecPlaneNormal.x ); // dir
WRITE_COORD( tr.vecPlaneNormal.y );
WRITE_COORD( tr.vecPlaneNormal.z );
WRITE_SHORT( iBSquidSpitSprite ); // model
WRITE_BYTE( 5 ); // count
WRITE_BYTE( 30 ); // speed
WRITE_BYTE( 80 ); // noise ( client will divide by 100 )
MESSAGE_END();
if( pOther->IsPlayer() )
{
ClearMultiDamage();
pOther->TraceAttack( pevOwner, 30, pev->origin + pev->velocity, &tr, DMG_GENERIC );
ApplyMultiDamage( pev, pevOwner );
}
SetThink( &CBaseEntity::SUB_Remove );
pev->nextthink = gpGlobals->time;
}
#include "BMOD_hornetgun.h"
LINK_ENTITY_TO_CLASS( weapon_hornetgun, CHgun )
//=========================================================
// ClearBeams - remove all beams
//=========================================================
void CHgun::ClearBeams()
{
for( int i = 0; i < HGUN_MAX_BEAMS; i++ )
{
if( m_pBeam[i] )
{
UTIL_Remove( m_pBeam[i] );
m_pBeam[i] = NULL;
}
}
m_iBeams = 0;
STOP_SOUND( ENT(m_pPlayer->pev), CHAN_WEAPON, "debris/zap4.wav" );
}
//=========================================================
// ArmBeam - small beam from arm to nearby geometry
//=========================================================
void CHgun::ArmBeam( Vector color )
{
TraceResult tr;
float flDist = 1.0;
if( m_iBeams >= HGUN_MAX_BEAMS )
return;
// UTIL_MakeAimVectors( pev->angles );
Vector vecSrc = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -12;
for( int i = 0; i < 3; i++ )
{
Vector vecAim = gpGlobals->v_right * RANDOM_FLOAT( -1, 1 ) + gpGlobals->v_up * RANDOM_FLOAT( -1, 1 );
TraceResult tr1;
UTIL_TraceLine( vecSrc, vecSrc + vecAim * 512, dont_ignore_monsters, ENT( m_pPlayer->pev ), &tr1 );
if( flDist > tr1.flFraction )
{
tr = tr1;
flDist = tr.flFraction;
}
}
// Couldn't find anything close enough
if( flDist == 1.0 )
return;
// DecalGunshot( &tr, BULLET_PLAYER_CROWBAR );
m_pBeam[m_iBeams] = CBeam::BeamCreate( "sprites/lgtning.spr", 30 );
if( !m_pBeam[m_iBeams] )
return;
m_pBeam[m_iBeams]->PointEntInit( tr.vecEndPos, m_pPlayer->entindex() );
m_pBeam[m_iBeams]->SetEndAttachment( 1 );
// m_pBeam[m_iBeams]->SetColor( 96, 128, 16 );
m_pBeam[m_iBeams]->SetColor( color.x, color.y, color.z );
m_pBeam[m_iBeams]->SetBrightness( 64 );
m_pBeam[m_iBeams]->SetNoise( 80 );
m_pBeam[m_iBeams]->pev->spawnflags |= SF_BEAM_TEMPORARY;
m_iBeams++;
}
//=========================================================
// ZapBeam - heavy damage directly forward
//=========================================================
void CHgun::ZapBeam( void )
{
Vector vecSrc, vecAim, vecOrig;
TraceResult tr;
CBaseEntity *pEntity;
/*
if (m_iBeams >= HGUN_MAX_BEAMS)
return;
*/
// UTIL_MakeVectors( m_pPlayer->pev->v_angle );
vecOrig = m_pPlayer->GetGunPosition();
vecSrc = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -12;
vecAim = gpGlobals->v_forward;
UTIL_TraceLine( vecOrig, vecOrig + vecAim * 2048, dont_ignore_monsters, ENT( m_pPlayer->pev ), &tr );
for( int i = 0; i < 2; i++ )
{
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
WRITE_BYTE( TE_BEAMPOINTS );
WRITE_COORD( vecSrc.x );
WRITE_COORD( vecSrc.y );
WRITE_COORD( vecSrc.z );
WRITE_COORD( tr.vecEndPos.x );
WRITE_COORD( tr.vecEndPos.y );
WRITE_COORD( tr.vecEndPos.z );
WRITE_SHORT( iZapBeamSpr );
WRITE_BYTE( 0 ); // Starting frame
WRITE_BYTE( 0 ); // framerate * 0.1
WRITE_BYTE( 2 ); // life * 0.1
WRITE_BYTE( 50 ); // width
WRITE_BYTE( 20 ); // noise
WRITE_BYTE( 180 ); // color r,g,b
WRITE_BYTE( 255 ); // color r,g,b
WRITE_BYTE( 96 ); // color r,g,b
WRITE_BYTE( 255 ); // brightness
WRITE_BYTE( 0 ); // scroll speed
MESSAGE_END();
}
UTIL_DecalTrace( &tr, DECAL_SMALLSCORCH1 + RANDOM_LONG( 0, 2 ) );
/*
m_pBeam[m_iBeams] = CBeam::BeamCreate( "sprites/lgtning.spr", 50 );
if( !m_pBeam[m_iBeams] )
return;
m_pBeam[m_iBeams]->PointEntInit( tr.vecEndPos, m_pPlayer->entindex() );
m_pBeam[m_iBeams]->SetEndAttachment( 1 );
m_pBeam[m_iBeams]->SetColor( 180, 255, 96 );
m_pBeam[m_iBeams]->SetBrightness( 255 );
m_pBeam[m_iBeams]->SetNoise( 20 );
m_pBeam[m_iBeams]->pev->spawnflags |= SF_BEAM_TEMPORARY;
m_iBeams++;
*/
pEntity = CBaseEntity::Instance(tr.pHit);
if( pEntity != NULL && pEntity->pev->takedamage )
{
// pEntity->TakeDamage( pev, VARS (pev->owner), 45, DMG_SHOCK );
ClearMultiDamage();
entvars_t *Owner;
Owner = VARS( pev->owner );
pEntity->TraceAttack( Owner, 90, vecAim, &tr, DMG_SHOCK | DMG_ALWAYSGIB );
ApplyMultiDamage( pev, Owner );
UTIL_ScreenFade( pEntity, Vector(180,255,96), 2, 0.5, 128, FFADE_IN );
}
UTIL_EmitAmbientSound( ENT( m_pPlayer->pev ), tr.vecEndPos, "weapons/electro4.wav", 0.5, ATTN_NORM, 0, RANDOM_LONG( 140, 160 ) );
if( UTIL_PointContents( tr.vecEndPos ) == CONTENTS_WATER )
{
CBaseEntity *pRift = CBaseEntity::Create( "zaprift", tr.vecEndPos, UTIL_VecToAngles( tr.vecPlaneNormal ), m_pPlayer->edict() );
// UTIL_EmitAmbientSound( ENT(m_pPlayer->pev), tr.vecEndPos, "weapons/electro4.wav", 50, ATTN_NORM, 0, 300 );
}
}
//=========================================================
// Freeze Ray -
//=========================================================
void CHgun::FreezeRay( void )
{
Vector vecSrc, vecAim, vecOrig;
TraceResult tr;
CBaseEntity *pEntity;
if( ( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < 12 ) || m_pPlayer->pev->waterlevel == 3 )
{
return;
}
vecOrig = m_pPlayer->GetGunPosition();
vecSrc = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -12;
vecAim = gpGlobals->v_forward;
UTIL_TraceLine( vecOrig, vecOrig + vecAim * 2048, dont_ignore_monsters, ENT( m_pPlayer->pev ), &tr );
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
WRITE_BYTE( TE_BEAMPOINTS );
WRITE_COORD( vecSrc.x );
WRITE_COORD( vecSrc.y );
WRITE_COORD( vecSrc.z );
WRITE_COORD( tr.vecEndPos.x );
WRITE_COORD( tr.vecEndPos.y );
WRITE_COORD( tr.vecEndPos.z );
WRITE_SHORT( iZapBeamSpr );
WRITE_BYTE( 0 ); // Starting frame
WRITE_BYTE( 0 ); // framerate * 0.1
WRITE_BYTE( 3 ); // life * 0.1
WRITE_BYTE( 200 ); // width
WRITE_BYTE( 2 ); // noise
WRITE_BYTE( 220 ); // color r,g,b
WRITE_BYTE( 220 ); // color r,g,b
WRITE_BYTE( 255 ); // color r,g,b
WRITE_BYTE( 255 ); // brightness
WRITE_BYTE( 0 ); // scroll speed
MESSAGE_END();
UTIL_DecalTrace( &tr, DECAL_MOMMASPLAT );
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
WRITE_BYTE( TE_SPRITETRAIL );// TE_RAILTRAIL);
WRITE_COORD( vecSrc.x );
WRITE_COORD( vecSrc.y );
WRITE_COORD( vecSrc.z );
WRITE_COORD( tr.vecEndPos.x );
WRITE_COORD( tr.vecEndPos.y );
WRITE_COORD( tr.vecEndPos.z );
WRITE_SHORT( m_sGlowSpr ); // model
WRITE_BYTE( 20 ); // count
WRITE_BYTE( 10 ); // life * 10
WRITE_BYTE( RANDOM_LONG( 1, 2 ) ); // size * 10
WRITE_BYTE( 10 ); // amplitude * 0.1
WRITE_BYTE( 0 ); // speed * 100
MESSAGE_END();
pEntity = CBaseEntity::Instance( tr.pHit );
if( pEntity != NULL && pEntity->pev->takedamage && pEntity->IsPlayer() )
{
CBasePlayer *pPlayer = (CBasePlayer *)pEntity;
UTIL_ScreenFade( pPlayer, Vector( 0, 0, 255 ), 2.0, 1.0, 128, FFADE_IN );
pPlayer->pev->rendermode = kRenderNormal;
pPlayer->pev->renderfx = kRenderFxGlowShell;
pPlayer->pev->rendercolor.x = 240; // red
pPlayer->pev->rendercolor.y = 240; // green
pPlayer->pev->rendercolor.z = 255; // blue
pPlayer->pev->renderamt = 60; // glow shell distance from entity
float freezetime = max (.6, bm_freezetime.value);
// freeze the player and set the "unfreeze" time...
pPlayer->EnableControl(FALSE);
pPlayer->m_vFreezeAngle = pPlayer->pev->v_angle;
// pPlayer->pev->movetype = MOVETYPE_TOSS;
pPlayer->m_flFreezeTime = gpGlobals->time + freezetime;
//RuneMsg( pPlayer, "YOU ARE FROZEN!!!", Vector(100,100,255), freezetime - .5);
PrintMessage( pPlayer, BMOD_CHAN_RUNE, Vector(100,100,255), Vector (.1, freezetime - .5, .1), "YOU ARE FROZEN!!!");
}
UTIL_EmitAmbientSound( ENT(m_pPlayer->pev), tr.vecEndPos, "weapons/electro4.wav", 0.5, ATTN_NORM, 0, RANDOM_LONG( 140, 160 ));
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] = 0;
m_flNextPrimaryAttack = gpGlobals->time + .25;
m_flRechargeTime = gpGlobals->time + 0.5;
m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = DIM_GUN_FLASH;
SendWeaponAnim( HGUN_SHOOT );
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT( 10, 15 );
m_pPlayer->pev->punchangle.x = RANDOM_FLOAT( 0, 2 );
}
//=========================================================
// BeamGlow - brighten all beams
//=========================================================
void CHgun::BeamGlow()
{
int b = m_iBeams * 32;
if( b > 255 )
b = 255;
for( int i = 0; i < m_iBeams; i++ )
{
if( m_pBeam[i]->GetBrightness() != 255 )
{
m_pBeam[i]->SetBrightness( b );
}
}
}
BOOL CHgun::IsUseable( void )
{
return TRUE;
}
void CHgun::Spawn()
{
Precache();
m_iId = WEAPON_HORNETGUN;
SET_MODEL( ENT( pev ), "models/w_hgun.mdl" );
m_iDefaultAmmo = HIVEHAND_DEFAULT_GIVE;
m_iFirePhase = 0;
m_iFireMode = 0;
FallInit();// get ready to fall down.
}
void CHgun::Precache( void )
{
PRECACHE_MODEL( "models/v_hgun.mdl" );
PRECACHE_MODEL( "models/w_hgun.mdl" );
PRECACHE_MODEL( "models/p_hgun.mdl" );
m_usHornetFire = PRECACHE_EVENT( 1, "events/firehornet.sc" );
UTIL_PrecacheOther( "hornet" );
UTIL_PrecacheOther( "zaprift" );
UTIL_PrecacheOther( "zapbounce" );
PRECACHE_SOUND( "debris/zap4.wav" );
PRECACHE_SOUND( "weapons/electro4.wav" );
PRECACHE_SOUND( "hassault/hw_shoot1.wav" );
iZapBeamSpr = PRECACHE_MODEL( "sprites/lgtning.spr" );
PRECACHE_MODEL( "sprites/bigspit.spr" );
iBSquidSpitSprite = PRECACHE_MODEL( "sprites/tinyspit.spr" );// client side spittle.
PRECACHE_SOUND( "bullchicken/bc_acid1.wav" );
PRECACHE_SOUND( "bullchicken/bc_spithit1.wav" );
PRECACHE_SOUND( "bullchicken/bc_spithit2.wav" );
PRECACHE_SOUND( "bullchicken/bc_attack2.wav" );
PRECACHE_SOUND( "bullchicken/bc_attack3.wav" );
PRECACHE_SOUND( "leech/leech_bite1.wav" );
m_sGlowSpr = PRECACHE_MODEL( "sprites/glow04.spr" );
}
int CHgun::AddToPlayer( CBasePlayer *pPlayer )
{
if( CBasePlayerWeapon::AddToPlayer( pPlayer ) )
{
#ifndef CLIENT_DLL
if( g_pGameRules->IsMultiplayer() )
{
// in multiplayer, all hivehands come full.
pPlayer->m_rgAmmo[PrimaryAmmoIndex()] = 12;
}
#endif
MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev );
WRITE_BYTE( m_iId );
MESSAGE_END();
return TRUE;
}
return FALSE;
}
int CHgun::GetItemInfo( ItemInfo *p )
{
p->pszName = STRING( pev->classname );
p->pszAmmo1 = "Hornets";
p->iMaxAmmo1 = m_iMaxammo;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = WEAPON_NOCLIP;
p->iSlot = 3;
p->iPosition = 3;
p->iId = m_iId = WEAPON_HORNETGUN;
p->iFlags = ITEM_FLAG_NOAUTOSWITCHEMPTY | ITEM_FLAG_NOAUTORELOAD;
p->iWeight = HORNETGUN_WEIGHT;
return 1;
}
BOOL CHgun::Deploy()
{
// BMOD Edit - Modified hornet message
if( bm_hornet_mod.value )
PrintMessage( m_pPlayer, BMOD_CHAN_WEAPON, Vector( 20, 250, 20 ), Vector( 1, 4, 2 ), "HORNET GUN\nACID SPIT - LIGHTNING - FREEZE RAY - SNARKS\nSECONDARY FIRE: Switches modes." );
return DefaultDeploy( "models/v_hgun.mdl", "models/p_hgun.mdl", HGUN_UP, "hive" );
}
void CHgun::Holster( int skiplocal /* = 0 */ )
{
ClearBeams();
m_iFirePhase = HGUN_IDLE;
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
SendWeaponAnim( HGUN_DOWN );
//!!!HACKHACK - can't select hornetgun if it's empty! no way to get ammo for it, either.
if( !m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()] )
{
m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()] = 1;
}
}
void CHgun::SecondaryAttack()
{
if( !bm_hornet_mod.value )
{
OldSecondaryAttack();
return;
}
m_iFireMode = ( m_iFireMode + 1 ) % 5;
switch( m_iFireMode )
{
case 0:
PrintMessage( m_pPlayer, BMOD_CHAN_WEAPON, Vector( 20, 250, 20 ), Vector( 1, 4, 2 ), "\n\nAcid Spit Mode - 3 per shot");
break;
case 1:
PrintMessage( m_pPlayer, BMOD_CHAN_WEAPON, Vector( 20, 250, 20 ), Vector( 1, 4, 2 ), "\n\nLightning Mode - 4 per shot");
break;
case 2:
PrintMessage( m_pPlayer, BMOD_CHAN_WEAPON, Vector( 20, 250, 20 ), Vector( 1, 4, 2 ), "\n\nMultizap Mode - 12 per shot");
break;
case 3:
PrintMessage( m_pPlayer, BMOD_CHAN_WEAPON, Vector( 20, 250, 20 ), Vector( 1, 4, 2 ), "\n\nFreeze Ray Mode - 12 per shot");
break;
case 4:
PrintMessage( m_pPlayer, BMOD_CHAN_WEAPON, Vector( 20, 250, 20 ), Vector( 1, 4, 2 ), "\n\nSnark Launcher Mode - 1 Snark per shot");
break;
}
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, "leech/leech_bite1.wav", 1, ATTN_NORM );
m_flNextSecondaryAttack = gpGlobals->time + .5;
}
void CHgun::ZapGun()
{
if( m_iFirePhase == HGUN_IDLE )
Reload();
if( ( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < 4 ) || ( m_fNextPhaseTime > gpGlobals->time ) )
{
return;
}
if( m_pPlayer->pev->waterlevel > 0 )
{
// m_pPlayer->TakeDamage( VARS( eoNullEntity ), VARS( eoNullEntity ), 50, DMG_SHOCK );
UTIL_ScreenFade( this, Vector( 180, 255, 96 ), 2, 0.5, 128, FFADE_IN );
CBaseEntity *pRift = CBaseEntity::Create( "zaprift", pev->origin, pev->angles, ENT( pev ) );
m_pPlayer->TakeDamage( m_pPlayer->pev, m_pPlayer->pev, 100, DMG_SHOCK );
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_WEAPON, "debris/zap4.wav", 1, ATTN_NORM, 0, 100 + m_iBeams * 10 );
m_flNextPrimaryAttack = m_flNextPrimaryAttack + 1.5;
return;
}
switch( m_iFirePhase )
{
case HGUN_IDLE:
m_flTimeWeaponIdle = gpGlobals->time;
m_iFirePhase = HGUN_CHARGE;
m_fNextPhaseTime = 0;
m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = DIM_GUN_FLASH;
case HGUN_CHARGE:
if( m_fNextPhaseTime < gpGlobals->time )
{
if( m_iBeams < HGUN_MAX_BEAMS )
{
ArmBeam( Vector( 96, 128, 16 ) );
BeamGlow();
m_fNextPhaseTime = gpGlobals->time + HGUN_CHARGE_TIME;
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_WEAPON, "debris/zap4.wav", 1, ATTN_NORM, 0,100 + m_iBeams * 10 );
}
else
{
m_iFirePhase = HGUN_ZAP;
m_fNextPhaseTime = gpGlobals->time + .1;
}
}
break;
case HGUN_ZAP:
ClearBeams();
ZapBeam();
m_iFirePhase = HGUN_ZAP_DONE;
m_fNextPhaseTime = gpGlobals->time + HGUN_ZAP_TIME;
EMIT_SOUND_DYN( ENT(m_pPlayer->pev), CHAN_WEAPON, "hassault/hw_shoot1.wav", 1, ATTN_NORM, 0, RANDOM_LONG( 130, 160 ) );
SendWeaponAnim( HGUN_SHOOT );
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= 4;
m_flRechargeTime = gpGlobals->time + 0.5;
m_pPlayer->pev->punchangle.x = RANDOM_FLOAT( 0, 2 );
break;
case HGUN_ZAP_DONE:
ClearBeams();
m_flNextPrimaryAttack = gpGlobals->time + .25;
m_flTimeWeaponIdle = gpGlobals->time + .1;
break;
}
}
void CHgun::MultiZapGun()
{
CZapBounce *pRift = NULL;
if( m_iFirePhase == HGUN_IDLE )
Reload();
if( ( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < 12 ) || ( m_fNextPhaseTime > gpGlobals->time ) )
{
return;
}
if( m_pPlayer->pev->waterlevel > 0 )
{
UTIL_ScreenFade( this, Vector( 180, 255, 96 ), 2, 0.5, 128, FFADE_IN );
m_pPlayer->TakeDamage( m_pPlayer->pev, m_pPlayer->pev, 100, DMG_SHOCK );
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_WEAPON, "debris/zap4.wav", 1, ATTN_NORM, 0, 100 + m_iBeams * 10 );
m_flNextPrimaryAttack = m_flNextPrimaryAttack + 1.5;
return;
}
switch( m_iFirePhase )
{
case HGUN_IDLE:
m_flTimeWeaponIdle = gpGlobals->time;
m_iFirePhase = HGUN_CHARGE;
m_fNextPhaseTime = 0;
m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = DIM_GUN_FLASH;
case HGUN_CHARGE:
if( m_fNextPhaseTime < gpGlobals->time )
{
if( m_iBeams < HGUN_MAX_BEAMS / 2 )
{
ArmBeam( Vector( 16, 96, 128 ) );
BeamGlow();
m_fNextPhaseTime = gpGlobals->time + HGUN_CHARGE_TIME;
EMIT_SOUND_DYN( ENT(m_pPlayer->pev), CHAN_WEAPON, "debris/zap4.wav", 1, ATTN_NORM, 0,100 + m_iBeams * 10 );
}
else
m_iFirePhase = HGUN_ZAP;
m_fNextPhaseTime = gpGlobals->time + .1;
}
break;
case HGUN_ZAP:
ClearBeams();
pRift = (CZapBounce*)CBaseEntity::Create( "zapbounce",
m_pPlayer->GetGunPosition( ) + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -12,
gpGlobals->v_forward,
m_pPlayer->edict() );
if( pRift )
{
pRift->m_fDamage = 90;
pRift->m_iBounce = 5;
pRift->pentIgnore = ENT( m_pPlayer->pev );
pRift->m_bFirstZap = TRUE;
pRift->BounceThink();
}
m_iFirePhase = HGUN_ZAP_DONE;
m_fNextPhaseTime = gpGlobals->time + HGUN_ZAP_TIME;
EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_WEAPON, "hassault/hw_shoot1.wav", 1, ATTN_NORM, 0, RANDOM_LONG( 130, 160 ) );
SendWeaponAnim( HGUN_SHOOT );
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= 12;
m_flRechargeTime = gpGlobals->time + 0.5;
m_pPlayer->pev->punchangle.x = RANDOM_FLOAT( 0, 2 );
break;
case HGUN_ZAP_DONE:
ClearBeams();
m_flNextPrimaryAttack = gpGlobals->time + .25;
m_flTimeWeaponIdle = gpGlobals->time + .1;
break;
}
}
void CHgun::PrimaryAttack( void )
{
if( !bm_hornet_mod.value )
{
OldPrimaryAttack();
return;
}
Reload();
switch( m_iFireMode )
{
case 0:
SquidSpit();
break;
case 1:
ZapGun();
break;
case 2:
MultiZapGun();
break;
case 3:
FreezeRay();
break;
case 4:
LaunchSnark();
break;
}
}
void CHgun::SquidSpit( void )
{
if( ( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < 3 ) || ( m_iFirePhase != HGUN_IDLE ) )
{
return;
}
Vector vecSrc, vecDir, vecOrig;
int iSpittle, iSpitSpeed;
TraceResult tr;
// UTIL_MakeVectors( m_pPlayer->pev->v_angle );
// Vector anglesAim = m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle;
// UTIL_MakeVectors( anglesAim );
vecOrig = m_pPlayer->GetGunPosition();
vecSrc = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -12;
// vecDir = m_pPlayer->pev->v_angle;
// vecDir = m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
vecDir = gpGlobals->v_forward;
UTIL_TraceLine( vecOrig, vecOrig + vecDir * 2048, dont_ignore_monsters, ENT( m_pPlayer->pev ), &tr );
vecDir = ( tr.vecEndPos - vecSrc ).Normalize();
if( m_pPlayer->pev->waterlevel == 3 )
{
iSpittle = 15;
iSpitSpeed = 120;
}
else
{
// CSquidSpit::Shoot( m_pPlayer->edict(), vecSrc, vecDir * 900 );
// CBaseEntity *pSpit = CBaseEntity::Create( "squidspit", vecSrc, vecDir , pev->owner );
BMODSquidSpit::Shoot( m_pPlayer->pev, vecSrc, vecDir * 1100 );
iSpittle = 5;
iSpitSpeed = 80;
}
m_flNextPrimaryAttack = gpGlobals->time + .25;
// spew the spittle temporary ents.
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSrc );
WRITE_BYTE( TE_SPRITE_SPRAY );
WRITE_COORD( vecSrc.x ); // pos
WRITE_COORD( vecSrc.y );
WRITE_COORD( vecSrc.z );
WRITE_COORD( vecDir.x ); // dir
WRITE_COORD( vecDir.y );
WRITE_COORD( vecDir.z );
WRITE_SHORT( iBSquidSpitSprite ); // model
WRITE_BYTE( iSpittle ); // count
WRITE_BYTE( iSpitSpeed ); // speed
WRITE_BYTE( 25 ); // noise ( client will divide by 100 )
MESSAGE_END();
switch( RANDOM_LONG( 0, 1 ) )
{
case 0:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, "bullchicken/bc_attack2.wav", 1, ATTN_NORM );
break;
case 1:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, "bullchicken/bc_attack3.wav", 1, ATTN_NORM );
break;
}
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= 3;
m_flRechargeTime = gpGlobals->time + 0.5;
m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = DIM_GUN_FLASH;
SendWeaponAnim( HGUN_SHOOT );
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT ( 10, 15 );
m_pPlayer->pev->punchangle.x = RANDOM_FLOAT( 0, 2 );
}
void CHgun::LaunchSnark( void )
{
if( ( m_pPlayer->m_rgAmmo[m_pPlayer->GetAmmoIndex( "Snarks" )] < 1 ) || ( m_iFirePhase != HGUN_IDLE ) )
{
return;
}
Vector vecSrc, vecDir, vecOrig;
int iSpittle, iSpitSpeed;
TraceResult tr;
vecOrig = m_pPlayer->GetGunPosition();
vecSrc = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -12;
// vecDir = m_pPlayer->pev->v_angle;
// vecDir = m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
vecDir = gpGlobals->v_forward;
UTIL_TraceLine( vecSrc + gpGlobals->v_forward * 20, vecSrc + gpGlobals->v_forward * 40, dont_ignore_monsters, NULL, &tr );
vecDir = ( tr.vecEndPos - vecSrc ).Normalize();
if( m_pPlayer->pev->waterlevel == 3 )
{
iSpittle = 15;
iSpitSpeed = 120;
}
else
{
CBaseEntity *pSqueak = CBaseEntity::Create( "monster_snark", tr.vecEndPos, m_pPlayer->pev->v_angle, m_pPlayer->edict() );
pSqueak->pev->velocity = gpGlobals->v_forward * 1500 + m_pPlayer->pev->velocity;
( (CSqueakGrenade*)pSqueak )->m_bWasLaunched = TRUE;
EMIT_SOUND_DYN( ENT( pSqueak->pev ), CHAN_VOICE, "squeek/sqk_hunt2.wav", 1, ATTN_NORM, 0, 105 );
iSpittle = 5;
iSpitSpeed = 80;
}
m_flNextPrimaryAttack = gpGlobals->time + .4;
// spew the spittle temporary ents.
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSrc );
WRITE_BYTE( TE_SPRITE_SPRAY );
WRITE_COORD( vecSrc.x ); // pos
WRITE_COORD( vecSrc.y );
WRITE_COORD( vecSrc.z );
WRITE_COORD( vecDir.x ); // dir
WRITE_COORD( vecDir.y );
WRITE_COORD( vecDir.z );
WRITE_SHORT( iBSquidSpitSprite ); // model
WRITE_BYTE( iSpittle ); // count
WRITE_BYTE( iSpitSpeed ); // speed
WRITE_BYTE( 25 ); // noise ( client will divide by 100 )
MESSAGE_END();
switch( RANDOM_LONG( 0, 1 ) )
{
case 0:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, "bullchicken/bc_attack2.wav", 1, ATTN_NORM );
break;
case 1:
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_WEAPON, "bullchicken/bc_attack3.wav", 1, ATTN_NORM );
break;
}
m_pPlayer->m_rgAmmo[m_pPlayer->GetAmmoIndex( "Snarks" )] -= 1;
m_flRechargeTime = gpGlobals->time + 0.5;
m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = DIM_GUN_FLASH;
SendWeaponAnim( HGUN_SHOOT );
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT( 10, 15 );
m_pPlayer->pev->punchangle.x = RANDOM_FLOAT( 0, 2 );
}
void CHgun::OldPrimaryAttack()
{
Reload();
if(m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
{
return;
}
#ifndef CLIENT_DLL
UTIL_MakeVectors( m_pPlayer->pev->v_angle );
CBaseEntity *pHornet = CBaseEntity::Create( "hornet", m_pPlayer->GetGunPosition( ) + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -12, m_pPlayer->pev->v_angle, m_pPlayer->edict() );
pHornet->pev->velocity = gpGlobals->v_forward * 300;
m_flRechargeTime = gpGlobals->time + 0.5;
#endif
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--;
m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = DIM_GUN_FLASH;
int flags;
#if defined( CLIENT_WEAPONS )
flags = FEV_NOTHOST;
#else
flags = 0;
#endif
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usHornetFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, FIREMODE_TRACK, 0, 0, 0 );
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
m_flNextPrimaryAttack = m_flNextPrimaryAttack + 0.25;
if( m_flNextPrimaryAttack < UTIL_WeaponTimeBase() )
{
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.25;
}
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
}
void CHgun::OldSecondaryAttack( void )
{
Reload();
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 )
{
return;
}
//Wouldn't be a bad idea to completely predict these, since they fly so fast...
#ifndef CLIENT_DLL
CBaseEntity *pHornet;
Vector vecSrc;
UTIL_MakeVectors( m_pPlayer->pev->v_angle );
vecSrc = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -12;
m_iFirePhase++;
switch( m_iFirePhase )
{
case 1:
vecSrc = vecSrc + gpGlobals->v_up * 8;
break;
case 2:
vecSrc = vecSrc + gpGlobals->v_up * 8;
vecSrc = vecSrc + gpGlobals->v_right * 8;
break;
case 3:
vecSrc = vecSrc + gpGlobals->v_right * 8;
break;
case 4:
vecSrc = vecSrc + gpGlobals->v_up * -8;
vecSrc = vecSrc + gpGlobals->v_right * 8;
break;
case 5:
vecSrc = vecSrc + gpGlobals->v_up * -8;
break;
case 6:
vecSrc = vecSrc + gpGlobals->v_up * -8;
vecSrc = vecSrc + gpGlobals->v_right * -8;
break;
case 7:
vecSrc = vecSrc + gpGlobals->v_right * -8;
break;
case 8:
vecSrc = vecSrc + gpGlobals->v_up * 8;
vecSrc = vecSrc + gpGlobals->v_right * -8;
m_iFirePhase = 0;
break;
}
pHornet = CBaseEntity::Create( "hornet", vecSrc, m_pPlayer->pev->v_angle, m_pPlayer->edict() );
pHornet->pev->velocity = gpGlobals->v_forward * 1200;
pHornet->pev->angles = UTIL_VecToAngles( pHornet->pev->velocity );
pHornet->SetThink( &CHornet::StartDart );
m_flRechargeTime = gpGlobals->time + 0.5;
#endif
int flags;
#if defined( CLIENT_WEAPONS )
flags = FEV_NOTHOST;
#else
flags = 0;
#endif
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usHornetFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, FIREMODE_FAST, 0, 0, 0 );
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--;
m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = DIM_GUN_FLASH;
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.1;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
}
void CHgun::Reload( void )
{
m_iMaxammo = (bm_hornet_mod.value) ? 12 : 8;
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] >= m_iMaxammo )
return;
while( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < m_iMaxammo && m_flRechargeTime < gpGlobals->time )
{
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]++;
m_flRechargeTime += 0.5;
}
}
void CHgun::WeaponIdle( void )
{
Reload();
m_iFirePhase = HGUN_IDLE;
if( m_iBeams )
ClearBeams();
if( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
return;
int iAnim;
float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0, 1 );
if( flRand <= 0.75 )
{
iAnim = HGUN_IDLE1;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 30.0 / 16 * ( 2 );
}
else if( flRand <= 0.875 )
{
iAnim = HGUN_FIDGETSWAY;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 40.0 / 16.0;
}
else
{
iAnim = HGUN_FIDGETSHAKE;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 35.0 / 16.0;
}
SendWeaponAnim( iAnim );
}
#endif