|
|
|
/*
|
|
|
|
Copyright (c) 1999, Cold Ice Modification.
|
|
|
|
|
|
|
|
This code has been written by SlimShady ( darcuri@optonline.net )
|
|
|
|
|
|
|
|
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 and from the Cold Ice team.
|
|
|
|
|
|
|
|
Please if you use this code in any public form, please give us credit.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "extdll.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "cbase.h"
|
|
|
|
#include "monsters.h"
|
|
|
|
#include "weapons.h"
|
|
|
|
#include "nodes.h"
|
|
|
|
#include "player.h"
|
|
|
|
#include "soundent.h"
|
|
|
|
#include "shake.h"
|
|
|
|
#include "gamerules.h"
|
|
|
|
#include "effects.h"
|
|
|
|
#include "customentity.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define RAILGUN_PRIMARY_FIRE_VOLUME 450
|
|
|
|
#define RAIL_BEAM_SPRITE "sprites/xbeam1.spr"
|
|
|
|
|
|
|
|
enum railgun_e {
|
|
|
|
GAUSS_IDLE = 0,
|
|
|
|
GAUSS_IDLE2,
|
|
|
|
GAUSS_FIDGET,
|
|
|
|
GAUSS_SPINUP,
|
|
|
|
GAUSS_SPIN,
|
|
|
|
GAUSS_FIRE,
|
|
|
|
GAUSS_FIRE2,
|
|
|
|
GAUSS_HOLSTER,
|
|
|
|
GAUSS_DRAW
|
|
|
|
};
|
|
|
|
|
|
|
|
class CRailgun : public CBasePlayerWeapon
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
void Spawn( void );
|
|
|
|
void Precache( void );
|
|
|
|
int iItemSlot( void ) { return 4; }
|
|
|
|
int GetItemInfo(ItemInfo *p);
|
|
|
|
int AddToPlayer( CBasePlayer *pPlayer );
|
|
|
|
|
|
|
|
BOOL Deploy( void );
|
|
|
|
void Holster( void );
|
|
|
|
|
|
|
|
void PrimaryAttack( void );
|
|
|
|
void SecondaryAttack( void );
|
|
|
|
void WeaponIdle( void );
|
|
|
|
|
|
|
|
void StartFire( void );
|
|
|
|
void Fire( Vector vecOrigSrc, Vector vecDirShooting, float flDamage );
|
|
|
|
int m_iBalls;
|
|
|
|
int m_iGlow;
|
|
|
|
int m_iBeam;
|
|
|
|
|
|
|
|
// rail, rail, rail
|
|
|
|
void CreateTrail(Vector,Vector);
|
|
|
|
void EXPORT DestroyTrail(void);
|
|
|
|
void EXPORT UpdateTrail(void);
|
|
|
|
int current_phase;
|
|
|
|
CBeam* m_pBeam, *m_inBeam, *m_lBeam;
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
LINK_ENTITY_TO_CLASS( weapon_railgun, CRailgun );
|
|
|
|
LINK_ENTITY_TO_CLASS( weapon_gauss, CRailgun );
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
//=========================================================
|
|
|
|
|
|
|
|
void CRailgun::Spawn( )
|
|
|
|
{
|
|
|
|
pev->classname = MAKE_STRING("weapon_railgun");
|
|
|
|
Precache( );
|
|
|
|
m_iId = WEAPON_RAILGUN;
|
|
|
|
SET_MODEL(ENT(pev), "models/wmodels/w_railgun.mdl");
|
|
|
|
|
|
|
|
m_iDefaultAmmo = RAILGUN_DEFAULT_GIVE;
|
|
|
|
|
|
|
|
FallInit();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CRailgun::Precache( void )
|
|
|
|
{
|
|
|
|
PRECACHE_MODEL("models/wmodels/w_railgun.mdl");
|
|
|
|
PRECACHE_MODEL("models/vmodels/v_railgun.mdl");
|
|
|
|
PRECACHE_MODEL("models/pmodels/p_railgun.mdl");
|
|
|
|
|
|
|
|
PRECACHE_SOUND("weapons/railgun1.wav");
|
|
|
|
|
|
|
|
PRECACHE_MODEL( RAIL_BEAM_SPRITE );
|
|
|
|
m_iGlow = PRECACHE_MODEL ( "sprites/blueflare1.spr" );
|
|
|
|
m_iBalls = PRECACHE_MODEL( "sprites/blueflare1.spr" );
|
|
|
|
m_iBeam = PRECACHE_MODEL ( "sprites/smoke.spr" );
|
|
|
|
}
|
|
|
|
|
|
|
|
int CRailgun::AddToPlayer( CBasePlayer *pPlayer )
|
|
|
|
{
|
|
|
|
if ( CBasePlayerWeapon::AddToPlayer( pPlayer ) )
|
|
|
|
{
|
|
|
|
MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev );
|
|
|
|
WRITE_BYTE( m_iId );
|
|
|
|
MESSAGE_END();
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CRailgun::GetItemInfo(ItemInfo *p)
|
|
|
|
{
|
|
|
|
p->pszName = STRING(pev->classname);
|
|
|
|
p->pszAmmo1 = "slug";
|
|
|
|
p->iMaxAmmo1 = RAILGUN_MAX_CARRY;
|
|
|
|
p->pszAmmo2 = NULL;
|
|
|
|
p->iMaxAmmo2 = -1;
|
|
|
|
p->iMaxClip = WEAPON_NOCLIP;
|
|
|
|
p->iSlot = 3;
|
|
|
|
p->iPosition = 2;
|
|
|
|
p->iId = m_iId = WEAPON_RAILGUN;
|
|
|
|
p->iFlags = 0;
|
|
|
|
p->iWeight = RAILGUN_WEIGHT;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CRailgun::Deploy( )
|
|
|
|
{
|
|
|
|
return DefaultDeploy( "models/vmodels/v_railgun.mdl", "models/pmodels/p_railgun.mdl", GAUSS_DRAW, "gauss" );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CRailgun::Holster( )
|
|
|
|
{
|
|
|
|
m_pPlayer->m_flNextAttack = gpGlobals->time + 0.5;
|
|
|
|
SendWeaponAnim( GAUSS_HOLSTER );
|
|
|
|
}
|
|
|
|
void CRailgun::PrimaryAttack()
|
|
|
|
{
|
|
|
|
|
|
|
|
if (m_pPlayer->pev->waterlevel == 3)
|
|
|
|
{
|
|
|
|
PlayEmptySound( );
|
|
|
|
m_flNextSecondaryAttack = m_flNextPrimaryAttack = gpGlobals->time + 0.15;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < 2)
|
|
|
|
{
|
|
|
|
PlayEmptySound( );
|
|
|
|
m_pPlayer->m_flNextAttack = gpGlobals->time + 0.5;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME;
|
|
|
|
|
|
|
|
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= 2;
|
|
|
|
|
|
|
|
StartFire();
|
|
|
|
|
|
|
|
m_flTimeWeaponIdle = gpGlobals->time + 1.0;
|
|
|
|
m_flNextPrimaryAttack = gpGlobals->time + 1.0;
|
|
|
|
}
|
|
|
|
void CRailgun::SecondaryAttack()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
void CRailgun::CreateTrail(Vector a,Vector b)
|
|
|
|
{
|
|
|
|
current_phase = 0;
|
|
|
|
m_pBeam = CBeam::BeamCreate( RAIL_BEAM_SPRITE, 40 );
|
|
|
|
m_pBeam->PointsInit(a,b);
|
|
|
|
m_pBeam->SetFlags( BEAM_FSINE );
|
|
|
|
m_pBeam->SetColor( 0, 113, 230 );
|
|
|
|
m_pBeam->LiveForTime( 1 );
|
|
|
|
m_pBeam->SetScrollRate ( 10 );
|
|
|
|
m_pBeam->pev->spawnflags |= SF_BEAM_TEMPORARY;
|
|
|
|
m_inBeam = CBeam::BeamCreate( RAIL_BEAM_SPRITE, 20 );
|
|
|
|
m_inBeam->PointsInit(a,b);
|
|
|
|
m_inBeam->SetFlags( BEAM_FSINE );
|
|
|
|
m_inBeam->SetColor( 200, 200, 200 );
|
|
|
|
m_inBeam->pev->spawnflags |= SF_BEAM_TEMPORARY;
|
|
|
|
m_inBeam->LiveForTime( 1 );
|
|
|
|
m_inBeam->SetScrollRate ( 10 );
|
|
|
|
m_lBeam = CBeam::BeamCreate( RAIL_BEAM_SPRITE, 50 );
|
|
|
|
m_lBeam->PointsInit(a,b);
|
|
|
|
m_lBeam->SetFlags( BEAM_FSINE );
|
|
|
|
m_lBeam->SetColor( 200, 200, 200 );
|
|
|
|
m_lBeam->SetScrollRate ( 10 );
|
|
|
|
m_lBeam->pev->spawnflags |= SF_BEAM_TEMPORARY;
|
|
|
|
m_lBeam->LiveForTime( 1 );
|
|
|
|
UpdateTrail();
|
|
|
|
}
|
|
|
|
void CRailgun::UpdateTrail()
|
|
|
|
{
|
|
|
|
m_pBeam->SetNoise( 10 + current_phase * 2 );
|
|
|
|
m_pBeam->SetBrightness( 200 - current_phase * 20 );
|
|
|
|
m_inBeam->SetNoise( 5 + current_phase );
|
|
|
|
m_inBeam->SetBrightness( 200 - current_phase * 20 );
|
|
|
|
m_lBeam->SetNoise( 0 );
|
|
|
|
m_lBeam->SetBrightness( 200 );
|
|
|
|
|
|
|
|
current_phase++;
|
|
|
|
|
|
|
|
if(current_phase == 8)
|
|
|
|
{
|
|
|
|
SetThink(&CRailgun::DestroyTrail);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetThink(&CRailgun::UpdateTrail);
|
|
|
|
}
|
|
|
|
|
|
|
|
pev->nextthink=gpGlobals->time + 0.1;
|
|
|
|
}
|
|
|
|
void CRailgun::DestroyTrail()
|
|
|
|
{
|
|
|
|
current_phase = 0;
|
|
|
|
|
|
|
|
if ( m_pBeam )
|
|
|
|
{
|
|
|
|
UTIL_Remove( m_pBeam );
|
|
|
|
m_pBeam = NULL;
|
|
|
|
}
|
|
|
|
if ( m_inBeam )
|
|
|
|
{
|
|
|
|
UTIL_Remove( m_inBeam );
|
|
|
|
m_inBeam = NULL;
|
|
|
|
}
|
|
|
|
if ( m_lBeam )
|
|
|
|
{
|
|
|
|
UTIL_Remove( m_lBeam );
|
|
|
|
m_inBeam = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CRailgun::StartFire( void )
|
|
|
|
{
|
|
|
|
float flDamage;
|
|
|
|
|
|
|
|
UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle );
|
|
|
|
Vector vecAiming = gpGlobals->v_forward;
|
|
|
|
Vector vecSrc = m_pPlayer->GetGunPosition( );
|
|
|
|
|
|
|
|
flDamage = gSkillData.plrDmgRailgun;
|
|
|
|
m_pPlayer->pev->punchangle.x = -2;
|
|
|
|
|
|
|
|
float flZVel = m_pPlayer->pev->velocity.z;
|
|
|
|
|
|
|
|
SendWeaponAnim( GAUSS_FIRE2 );
|
|
|
|
|
|
|
|
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
|
|
|
|
|
|
|
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/railgun1.wav", 0.5 + flDamage * (1.0 / 400.0), ATTN_NORM, 0, 85 + RANDOM_LONG(0,0x1f));
|
|
|
|
|
|
|
|
Fire( vecSrc, vecAiming, flDamage );
|
|
|
|
}
|
|
|
|
void CRailgun::Fire( Vector vecOrigSrc, Vector vecDir, float flDamage )
|
|
|
|
{
|
|
|
|
m_pPlayer->m_iWeaponVolume = RAILGUN_PRIMARY_FIRE_VOLUME;
|
|
|
|
|
|
|
|
Vector vecSrc = vecOrigSrc;
|
|
|
|
Vector vecDest = vecSrc + vecDir * 8192;
|
|
|
|
edict_t *pentIgnore;
|
|
|
|
TraceResult tr, beam_tr;
|
|
|
|
|
|
|
|
pentIgnore = ENT( m_pPlayer->pev );
|
|
|
|
|
|
|
|
UTIL_TraceLine(vecSrc, vecDest, dont_ignore_monsters, pentIgnore, &tr);
|
|
|
|
|
|
|
|
CreateTrail(vecSrc + gpGlobals->v_up * -8 + gpGlobals->v_right * 3 ,tr.vecEndPos);
|
|
|
|
|
|
|
|
UTIL_TraceLine(vecSrc, vecDest, dont_ignore_monsters, pentIgnore, &tr);
|
|
|
|
|
|
|
|
if (tr.fAllSolid)
|
|
|
|
return;
|
|
|
|
|
|
|
|
CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit);
|
|
|
|
|
|
|
|
if (pEntity == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (pEntity->pev->takedamage)
|
|
|
|
{
|
|
|
|
ClearMultiDamage();
|
|
|
|
pEntity->TraceAttack( m_pPlayer->pev, flDamage, vecDir, &tr, DMG_BULLET | DMG_ALWAYSGIB );
|
|
|
|
ApplyMultiDamage(m_pPlayer->pev, m_pPlayer->pev);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Make some balls and a decal
|
|
|
|
DecalGunshot( &tr, BULLET_MONSTER_12MM );
|
|
|
|
|
|
|
|
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, tr.vecEndPos );
|
|
|
|
WRITE_BYTE( TE_GLOWSPRITE );
|
|
|
|
WRITE_COORD( tr.vecEndPos.x); // pos
|
|
|
|
WRITE_COORD( tr.vecEndPos.y);
|
|
|
|
WRITE_COORD( tr.vecEndPos.z);
|
|
|
|
WRITE_SHORT( m_iGlow ); // model
|
|
|
|
WRITE_BYTE( 20 ); // life * 10
|
|
|
|
WRITE_BYTE( 3 ); // size * 10
|
|
|
|
WRITE_BYTE( 200 ); // brightness
|
|
|
|
MESSAGE_END();
|
|
|
|
|
|
|
|
|
|
|
|
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, tr.vecEndPos );
|
|
|
|
WRITE_BYTE( TE_SPRITETRAIL );
|
|
|
|
WRITE_COORD( tr.vecEndPos.x );
|
|
|
|
WRITE_COORD( tr.vecEndPos.y );
|
|
|
|
WRITE_COORD( tr.vecEndPos.z );
|
|
|
|
WRITE_COORD( tr.vecEndPos.x + tr.vecPlaneNormal.x );
|
|
|
|
WRITE_COORD( tr.vecEndPos.y + tr.vecPlaneNormal.y );
|
|
|
|
WRITE_COORD( tr.vecEndPos.z + tr.vecPlaneNormal.z );
|
|
|
|
WRITE_SHORT( m_iBalls ); // model
|
|
|
|
WRITE_BYTE( 8 ); // count
|
|
|
|
WRITE_BYTE( 6 ); // life * 10
|
|
|
|
WRITE_BYTE( RANDOM_LONG( 1, 2 ) ); // size * 10
|
|
|
|
WRITE_BYTE( 10 ); // amplitude * 0.1
|
|
|
|
WRITE_BYTE( 20 ); // speed * 100
|
|
|
|
MESSAGE_END();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
vecSrc = tr.vecEndPos + vecDir;
|
|
|
|
pentIgnore = ENT( pEntity->pev );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CRailgun::WeaponIdle( void )
|
|
|
|
{
|
|
|
|
ResetEmptySound( );
|
|
|
|
|
|
|
|
if (m_flTimeWeaponIdle > gpGlobals->time)
|
|
|
|
return;
|
|
|
|
|
|
|
|
int iAnim;
|
|
|
|
float flRand = RANDOM_FLOAT(0, 1);
|
|
|
|
if (flRand <= 0.5)
|
|
|
|
{
|
|
|
|
iAnim = GAUSS_IDLE;
|
|
|
|
m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT ( 10, 15 );
|
|
|
|
}
|
|
|
|
else if (flRand <= 0.75)
|
|
|
|
{
|
|
|
|
iAnim = GAUSS_IDLE2;
|
|
|
|
m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT ( 10, 15 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
iAnim = GAUSS_FIDGET;
|
|
|
|
m_flTimeWeaponIdle = gpGlobals->time + 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
SendWeaponAnim( iAnim );
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
class CRailgunAmmo : public CBasePlayerAmmo
|
|
|
|
{
|
|
|
|
void Spawn( void )
|
|
|
|
{
|
|
|
|
Precache( );
|
|
|
|
SET_MODEL(ENT(pev), "models/w_gaussammo.mdl");
|
|
|
|
CBasePlayerAmmo::Spawn( );
|
|
|
|
}
|
|
|
|
void Precache( void )
|
|
|
|
{
|
|
|
|
PRECACHE_MODEL ("models/w_gaussammo.mdl");
|
|
|
|
PRECACHE_SOUND("items/9mmclip1.wav");
|
|
|
|
}
|
|
|
|
BOOL AddAmmo( CBaseEntity *pOther )
|
|
|
|
{
|
|
|
|
if (pOther->GiveAmmo( AMMO_RAILSLUG_GIVE, "slug", RAILGUN_MAX_CARRY ) != -1)
|
|
|
|
{
|
|
|
|
EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
LINK_ENTITY_TO_CLASS( ammo_railslug, CRailgunAmmo );
|
|
|
|
|