sin-2015/chaingun.cpp
1999-04-22 00:00:00 +00:00

226 lines
4.7 KiB
C++

// Copyright (C) 1998 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source is may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
// DESCRIPTION:
// High velocity chain gun
//
#include "g_local.h"
#include "bullet.h"
#include "chaingun.h"
#include "rocketlauncher.h"
#include "explosion.h"
#include "specialfx.h"
#include "misc.h"
#include "surface.h"
#define BULLET_MODE 1
CLASS_DECLARATION( Projectile, Grenade, "grenade" );
Event EV_Grenade_Explode( "grenade_explode" );
ResponseDef Grenade::Responses[] =
{
{ &EV_Touch, ( Response )Grenade::Grenade_Touch },
{ &EV_Grenade_Explode, ( Response )Grenade::Explode },
{ NULL, NULL }
};
EXPORT_FROM_DLL void Grenade::Grenade_Touch
(
Event *ev
)
{
Entity *other;
other = ev->GetEntity( 1 );
assert( other );
if ( other->entnum == owner )
return;
if ( HitSky() )
{
PostEvent( EV_Remove, 0 );
return;
}
if ( !other->takedamage || other->health <= 0 )
{
// Play a bouncy sound
RandomSound( "grenade_bounce", 1 );
return;
}
Explode( ev );
}
EXPORT_FROM_DLL void Grenade::Explode
(
Event *ev
)
{
int damg;
Vector v;
Entity *other;
Entity *owner;
other = ev->GetEntity( 1 );
assert( other );
if ( other->isSubclassOf( Teleporter ) )
{
return;
}
stopsound( CHAN_VOICE );
setSolidType( SOLID_NOT );
hideModel();
if ( HitSky() )
{
PostEvent( EV_Remove, 0 );
return;
}
owner = G_GetEntity( this->owner );
if ( !owner )
owner = world;
damg = 75 + ( int )G_Random( 25 );
if ( !deathmatch->value && owner->isClient() )
damg *= 1.5;
if ( other->takedamage )
other->Damage( this, owner, damg, worldorigin, velocity, level.impact_trace.plane.normal, 30, 0, MOD_GRENADE, -1, -1, 1.0f );
SpawnBlastDamage( &level.impact_trace, damg, owner );
v = velocity;
v.normalize();
// don't do radius damage to the other, because all the damage
// was done in the impact
v = worldorigin - v * 24;
CreateExplosion( v, damg, 1.0f, true, this, owner, other );
PostEvent( EV_Remove, 0.1 );
}
EXPORT_FROM_DLL void Grenade::Setup
(
Entity *owner,
Vector pos,
Vector forward,
Vector right,
Vector up
)
{
Event *ev;
setModel( "grenade.def" );
this->owner = owner->entnum;
edict->owner = owner->edict;
setMoveType( MOVETYPE_BOUNCE );
setSolidType( SOLID_BBOX );
takedamage = DAMAGE_YES;
edict->clipmask = MASK_PROJECTILE;
health = 10;
SetGravityAxis( owner->gravaxis );
velocity = forward * ( 500 + G_Random( 200 ) );
velocity += up * ( 200 + crandom() * 10.0 );
velocity += right * ( crandom() * 10.0 );
avelocity = "575 0 0";
ev = new Event( EV_Grenade_Explode );
ev->AddEntity( world );
PostEvent( ev, 2.5 + G_Random(1.0) );
edict->s.effects |= EF_ROCKET;
setOrigin( pos );
worldorigin.copyTo( edict->s.old_origin );
setSize( "-4 -4 -4", "4 4 4" );
edict->s.effects |= EF_EVERYFRAME;
RandomAnimate( "smoke", NULL );
//### give it a heat signature
edict->s.effects |= EF_WARM;
//###
}
CLASS_DECLARATION( BulletWeapon, ChainGun, "weapon_highvelocitygun" );
ResponseDef ChainGun::Responses[] =
{
{ &EV_Weapon_Shoot, ( Response )ChainGun::Shoot },
{ NULL, NULL }
};
ChainGun::ChainGun
(
)
{
#ifdef SIN_DEMO
PostEvent( EV_Remove, 0 );
return;
#endif
SetModels( "hvgun.def", "view_hvgun.def" );
SetAmmo( "Bullet50mm", 1, 30 );
SetSecondaryAmmo( "Rockets", 1, 5);
SetRank( 50, 50 );
SetType( WEAPON_2HANDED_LO );
dualmode = true;
modelIndex( "grenade.def" );
modelIndex( "rocket.def" );
modelIndex( "rockets.def" );
modelIndex( "50mm.def" );
modelIndex( "sprites/blastmark.spr" );
modelIndex( "sprites/hvblast.spr" );
modelIndex( "sprites/tracer.spr" );
modelIndex( "hvshell.def" );
}
void ChainGun::Shoot
(
Event *ev
)
{
if ( weaponmode == PRIMARY )
{
// if ( deathmatch->value )
// FireBullets( 1, "300 300 300", 24, 32, DAMAGE_BULLET, MOD_CHAINGUN, false );
// else
FireBullets( 1, "300 300 300", 16, 24, DAMAGE_BULLET, MOD_CHAINGUN, false );
NextAttack( 0 );
}
else
{
Grenade *grenade;
Vector pos;
Vector forward;
Vector up;
Vector right;
GetMuzzlePosition( &pos, &forward, &up, &right );
grenade = new Grenade;
grenade->Setup( owner, pos, forward, up, right );
NextAttack( 0.8 );
}
}