Portable Half-Life SDK. GoldSource and Xash3D. Crossplatform.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

410 lines
8.7 KiB

/*
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 "gamerules.h"
#define BOLT_AIR_VELOCITY 2000
#define BOLT_WATER_VELOCITY 1000
class CCrossbowBolt : public CBaseEntity
{
void Spawn( void );
void Precache( void );
int Classify ( void );
void EXPORT BubbleThink( void );
void EXPORT BoltTouch( CBaseEntity *pOther );
public:
static CCrossbowBolt *BoltCreate( void );
};
LINK_ENTITY_TO_CLASS( crossbow_bolt, CCrossbowBolt );
CCrossbowBolt *CCrossbowBolt::BoltCreate( void )
{
CCrossbowBolt *pBolt = GetClassPtr( (CCrossbowBolt *)NULL );
pBolt->pev->classname = MAKE_STRING("bolt");
pBolt->Spawn();
return pBolt;
}
void CCrossbowBolt::Spawn( )
{
Precache( );
pev->movetype = MOVETYPE_FLY;
pev->solid = SOLID_BBOX;
pev->gravity = 0.5;
SET_MODEL(ENT(pev), "models/bolt.mdl");
UTIL_SetOrigin( pev, pev->origin );
UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0));
SetTouch( BoltTouch );
SetThink( BubbleThink );
pev->nextthink = gpGlobals->time + 0.2;
}
void CCrossbowBolt::Precache( )
{
PRECACHE_MODEL ("models/bolt.mdl");
PRECACHE_SOUND("weapons/xbow_hitbod1.wav");
PRECACHE_SOUND("weapons/xbow_hitbod2.wav");
PRECACHE_SOUND("weapons/xbow_fly1.wav");
PRECACHE_SOUND("weapons/xbow_hit1.wav");
}
int CCrossbowBolt :: Classify ( void )
{
return CLASS_NONE;
}
void CCrossbowBolt::BoltTouch( CBaseEntity *pOther )
{
SetTouch( NULL );
SetThink( NULL );
if (pOther->pev->takedamage)
{
TraceResult tr = UTIL_GetGlobalTrace( );
entvars_t *pevOwner;
pevOwner = VARS( pev->owner );
ClearMultiDamage( );
if ( pOther->IsPlayer() )
{
pOther->TraceAttack(pevOwner, gSkillData.plrDmgBoltgun, pev->velocity.Normalize(), &tr, DMG_NEVERGIB );
}
ApplyMultiDamage( pev, pevOwner );
UTIL_Remove(this); //remove!
pev->velocity = Vector( 0, 0, 0 );
switch( RANDOM_LONG(0,1) )
{
case 0:
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/xbow_hitbod1.wav", 1, ATTN_NORM); break;
case 1:
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/xbow_hitbod2.wav", 1, ATTN_NORM); break;
}
if ( !g_pGameRules->IsMultiplayer() )
{
Killed( pev, GIB_NEVER );
}
}
else
{
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "weapons/xbow_hit1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 98 + RANDOM_LONG(0,7));
SetThink( SUB_Remove );
pev->nextthink = gpGlobals->time;
if ( FClassnameIs( pOther->pev, "worldspawn" ) )
{
Vector vecDir = pev->velocity.Normalize( );
UTIL_SetOrigin( pev, pev->origin - vecDir * 12 );
pev->angles = UTIL_VecToAngles( vecDir );
pev->solid = SOLID_NOT;
pev->movetype = MOVETYPE_FLY;
pev->velocity = Vector( 0, 0, 0 );
pev->avelocity.z = 0;
pev->angles.z = RANDOM_LONG(0,360);
pev->nextthink = gpGlobals->time + .5;
}
if (UTIL_PointContents(pev->origin) != CONTENTS_WATER)
{
UTIL_Sparks( pev->origin );
}
}
}
void CCrossbowBolt::BubbleThink( void )
{
pev->nextthink = gpGlobals->time + 0.1;
if (pev->waterlevel == 0)
{
return;
}
UTIL_BubbleTrail( pev->origin - pev->velocity * 0.1, pev->origin, 1 );
}
enum boltgun_e {
CROSSBOW_IDLE1 = 0, // full
CROSSBOW_IDLE2, // empty
CROSSBOW_FIDGET1, // full
CROSSBOW_FIDGET2, // empty
CROSSBOW_FIRE1, // full
CROSSBOW_FIRE2, // reload
CROSSBOW_FIRE3, // empty
CROSSBOW_RELOAD, // from empty
CROSSBOW_DRAW1, // full
CROSSBOW_DRAW2, // empty
CROSSBOW_HOLSTER1, // full
CROSSBOW_HOLSTER2, // empty
};
class CBoltGun : public CBasePlayerWeapon
{
public:
void Spawn( void );
void Precache( void );
int iItemSlot( ) { return 3; }
int GetItemInfo(ItemInfo *p);
void FireBolt( void );
void PrimaryAttack( void );
int AddToPlayer( CBasePlayer *pPlayer );
BOOL Deploy( );
void Holster( );
void Reload( void );
void WeaponIdle( void );
};
LINK_ENTITY_TO_CLASS( weapon_boltgun, CBoltGun );
LINK_ENTITY_TO_CLASS( weapon_hornetgun, CBoltGun );
void CBoltGun::Spawn( )
{
pev->classname = MAKE_STRING("weapon_boltgun");
Precache( );
m_iId = WEAPON_BOLTGUN;
SET_MODEL(ENT(pev), "models/w_crossbow.mdl");
m_iDefaultAmmo = BOLTGUN_DEFAULT_GIVE;
FallInit();
}
int CBoltGun::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;
}
void CBoltGun::Precache( void )
{
PRECACHE_MODEL("models/w_crossbow.mdl");
PRECACHE_MODEL("models/v_crossbow.mdl");
PRECACHE_MODEL("models/p_crossbow.mdl");
PRECACHE_SOUND("weapons/xbow_reload1.wav");
PRECACHE_SOUND("weapons/boltgun1.wav");
UTIL_PrecacheOther( "crossbow_bolt" );
}
int CBoltGun::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = "bolts";
p->iMaxAmmo1 = BOLTGUN_MAX_CARRY;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = BOLTGUN_MAX_CLIP;
p->iSlot = 2;
p->iPosition = 6;
p->iId = WEAPON_BOLTGUN;
p->iFlags = 0;
p->iWeight = BOLTGUN_WEIGHT;
return 1;
}
BOOL CBoltGun::Deploy( )
{
if (m_iClip)
return DefaultDeploy( "models/v_crossbow.mdl", "models/p_crossbow.mdl", CROSSBOW_DRAW1, "bow" );
return DefaultDeploy( "models/v_crossbow.mdl", "models/p_crossbow.mdl", CROSSBOW_DRAW2, "bow" );
}
void CBoltGun::Holster( )
{
m_fInReload = FALSE;
m_pPlayer->m_flNextAttack = gpGlobals->time + 0.5;
if (m_iClip)
SendWeaponAnim( CROSSBOW_HOLSTER1 );
else
SendWeaponAnim( CROSSBOW_HOLSTER2 );
}
void CBoltGun::PrimaryAttack( void )
{
FireBolt();
}
void CBoltGun::FireBolt()
{
TraceResult tr;
if (m_iClip == 0)
{
PlayEmptySound( );
return;
}
m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME;
m_iClip--;
// make twang sound
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/boltgun1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 93 + RANDOM_LONG(0,0xF));
SendWeaponAnim( CROSSBOW_FIRE3 );
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
Vector anglesAim = m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle;
UTIL_MakeVectors( anglesAim );
anglesAim.x = -anglesAim.x;
Vector vecSrc = m_pPlayer->GetGunPosition( ) - gpGlobals->v_up * 2;
Vector vecDir = gpGlobals->v_forward;
CCrossbowBolt *pBolt = CCrossbowBolt::BoltCreate();
pBolt->pev->origin = vecSrc;
pBolt->pev->angles = anglesAim;
pBolt->pev->owner = m_pPlayer->edict();
if (m_pPlayer->pev->waterlevel == 3)
{
pBolt->pev->velocity = vecDir * BOLT_WATER_VELOCITY;
pBolt->pev->speed = BOLT_WATER_VELOCITY;
}
else
{
pBolt->pev->velocity = vecDir * BOLT_AIR_VELOCITY;
pBolt->pev->speed = BOLT_AIR_VELOCITY;
}
pBolt->pev->avelocity.z = 10;
m_flNextPrimaryAttack = gpGlobals->time + 0.1;
if (m_iClip != 0)
m_flTimeWeaponIdle = gpGlobals->time + 5.0;
else
m_flTimeWeaponIdle = 0.75;
m_pPlayer->pev->punchangle.x -= 1;
}
void CBoltGun::Reload( void )
{
if (DefaultReload( 30, CROSSBOW_RELOAD, 4.5 ))
{
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/xbow_reload1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 93 + RANDOM_LONG(0,0xF));
}
}
void CBoltGun::WeaponIdle( void )
{
m_pPlayer->GetAutoaimVector( AUTOAIM_2DEGREES ); // get the autoaim vector but ignore it; used for autoaim crosshair in DM
ResetEmptySound( );
if (m_flTimeWeaponIdle < gpGlobals->time)
{
float flRand = RANDOM_FLOAT(0, 1);
if (flRand <= 0.75)
{
if (m_iClip)
{
SendWeaponAnim( CROSSBOW_IDLE1 );
}
else
{
SendWeaponAnim( CROSSBOW_IDLE2 );
}
m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT ( 10, 15 );
}
else
{
if (m_iClip)
{
SendWeaponAnim( CROSSBOW_FIDGET1 );
m_flTimeWeaponIdle = gpGlobals->time + 90.0 / 30.0;
}
else
{
SendWeaponAnim( CROSSBOW_FIDGET2 );
m_flTimeWeaponIdle = gpGlobals->time + 80.0 / 30.0;
}
}
}
}
class CBoltGunAmmo : public CBasePlayerAmmo
{
void Spawn( void )
{
Precache( );
SET_MODEL(ENT(pev), "models/w_crossbow_clip.mdl");
CBasePlayerAmmo::Spawn( );
}
void Precache( void )
{
PRECACHE_MODEL ("models/w_crossbow_clip.mdl");
PRECACHE_SOUND("items/9mmclip1.wav");
}
BOOL AddAmmo( CBaseEntity *pOther )
{
if (pOther->GiveAmmo( AMMO_BOLTGUN_GIVE, "bolts", BOLTGUN_MAX_CARRY ) != -1)
{
EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM);
return TRUE;
}
return FALSE;
}
};
LINK_ENTITY_TO_CLASS( ammo_boltgun, CBoltGunAmmo );