215 lines
4.5 KiB
C++
215 lines
4.5 KiB
C++
// Copyright (C) 1997 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:
|
|
// Standard rocketlauncher, similar to the Quake and Doom rocketlaunchers.
|
|
//
|
|
|
|
#include "g_local.h"
|
|
#include "explosion.h"
|
|
#include "rocketlauncher.h"
|
|
#include "worldspawn.h"
|
|
#include "specialfx.h"
|
|
#include "misc.h"
|
|
#include "surface.h"
|
|
|
|
#define ROCKET_SPEED 1000
|
|
#define ROCKET_RADIUS 150 // FIXME: max damage (90 +rand(20)) + 40 == 150... hard coded. gotta pass this in
|
|
|
|
CLASS_DECLARATION( Projectile, Rocket, NULL );
|
|
|
|
Event EV_Rocket_Explode( "explode" );
|
|
|
|
ResponseDef Rocket::Responses[] =
|
|
{
|
|
{ &EV_Touch, ( Response )Rocket::Explode },
|
|
{ &EV_Rocket_Explode, ( Response )Rocket::Explode },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
EXPORT_FROM_DLL void Rocket::Explode
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
int damg;
|
|
Vector v;
|
|
Entity *other;
|
|
Entity *owner;
|
|
|
|
other = ev->GetEntity( 1 );
|
|
assert( other );
|
|
|
|
if ( other->isSubclassOf( Teleporter ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( other->entnum == this->owner )
|
|
{
|
|
return;
|
|
}
|
|
|
|
stopsound( CHAN_VOICE );
|
|
|
|
setSolidType( SOLID_NOT );
|
|
hideModel();
|
|
if ( HitSky() )
|
|
{
|
|
PostEvent( EV_Remove, 0 );
|
|
return;
|
|
}
|
|
|
|
damg = 90 + ( int )G_Random( 25 );
|
|
|
|
owner = G_GetEntity( this->owner );
|
|
|
|
if ( !owner )
|
|
owner = world;
|
|
|
|
// Single player packs a bigger punch
|
|
if ( !deathmatch->value && owner->isClient() )
|
|
damg *= 1.5;
|
|
|
|
if (other->takedamage)
|
|
other->Damage( this, owner, damg, worldorigin, velocity, level.impact_trace.plane.normal, 200, 0, MOD_ROCKET, -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 * 36;
|
|
CreateExplosion( v, damg, 1.0f, true, this, owner, other );
|
|
PostEvent( EV_Remove, 0.1 );
|
|
}
|
|
|
|
EXPORT_FROM_DLL void Rocket::Setup
|
|
(
|
|
Entity *owner,
|
|
Vector pos,
|
|
Vector dir
|
|
)
|
|
|
|
{
|
|
Event *ev;
|
|
|
|
this->owner = owner->entnum;
|
|
edict->owner = owner->edict;
|
|
|
|
setMoveType( MOVETYPE_FLYMISSILE );
|
|
setSolidType( SOLID_BBOX );
|
|
edict->clipmask = MASK_PROJECTILE;
|
|
|
|
angles = dir.toAngles();
|
|
angles[ PITCH ] = - angles[ PITCH ];
|
|
setAngles( angles );
|
|
|
|
speed = ROCKET_SPEED;
|
|
velocity = dir * ROCKET_SPEED;
|
|
|
|
// set missile duration
|
|
ev = new Event( EV_Remove );
|
|
ev->AddEntity( world );
|
|
PostEvent( ev, 20 );
|
|
|
|
takedamage = DAMAGE_YES;
|
|
health = 10;
|
|
|
|
setModel( "rocket.def" );
|
|
edict->s.renderfx |= RF_DLIGHT;
|
|
edict->s.effects |= EF_ROCKET;
|
|
edict->s.effects |= EF_EVERYFRAME;
|
|
edict->s.angles[ROLL] = rand() % 360;
|
|
avelocity = "0 0 90";
|
|
gravity = 0;
|
|
edict->s.color_r = 0.8;
|
|
edict->s.color_g = 0.4;
|
|
edict->s.color_b = 0;
|
|
edict->s.radius = 200;
|
|
|
|
//### give it a heat signature
|
|
edict->s.effects |= EF_WARM;
|
|
//###
|
|
|
|
// setup ambient thrust
|
|
ev = new Event( EV_RandomEntitySound );
|
|
ev->AddString( "thrust" );
|
|
ProcessEvent( ev );
|
|
|
|
setSize( "-1 -1 -1", "1 1 1" );
|
|
setOrigin( pos );
|
|
worldorigin.copyTo(edict->s.old_origin);
|
|
}
|
|
|
|
CLASS_DECLARATION( Weapon, RocketLauncher, "weapon_rocketlauncher" );
|
|
|
|
ResponseDef RocketLauncher::Responses[] =
|
|
{
|
|
{ &EV_Weapon_Shoot, ( Response )RocketLauncher::Shoot },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
//### for guided missile
|
|
void RocketLauncher::SecondaryUse (Event *ev)
|
|
{
|
|
// make sure he has it, but only in deathmatch
|
|
if(!owner->HasItem("MissileLauncher") && deathmatch->value)
|
|
owner->giveWeapon("MissileLauncher");
|
|
|
|
owner->useWeapon("MissileLauncher");
|
|
}
|
|
//###
|
|
|
|
RocketLauncher::RocketLauncher()
|
|
{
|
|
SetModels( "rlaunch.def", "view_rlaunch.def" );
|
|
modelIndex( "rocket.def" );
|
|
modelIndex( "rockets.def" );
|
|
modelIndex( "sprites/blastmark.spr" );
|
|
gi.soundindex( "weapons/rlaunch/stmmchn.wav" );
|
|
SetAmmo( "Rockets", 1, 5 );
|
|
SetRank( 70, 70 );
|
|
SetType( WEAPON_2HANDED_LO );
|
|
|
|
SetMinRange( ROCKET_RADIUS );
|
|
SetProjectileSpeed( ROCKET_SPEED );
|
|
|
|
//### precaches for the guided missile
|
|
if(deathmatch->value)
|
|
{
|
|
modelIndex("missile_w.def");
|
|
modelIndex("view_missile.def");
|
|
modelIndex("missile.def");
|
|
}
|
|
//###
|
|
}
|
|
|
|
void RocketLauncher::Shoot
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
Rocket *rocket;
|
|
Vector pos;
|
|
Vector dir;
|
|
|
|
assert( owner );
|
|
if ( !owner )
|
|
{
|
|
return;
|
|
}
|
|
|
|
GetMuzzlePosition( &pos, &dir );
|
|
|
|
rocket = new Rocket;
|
|
rocket->Setup( owner, pos, dir );
|
|
NextAttack( 1.0 );
|
|
}
|