sin-sdk/bullet.cpp

515 lines
14 KiB
C++

//-----------------------------------------------------------------------------
//
// $Logfile:: /Quake 2 Engine/Sin/code/game/bullet.cpp $
// $Revision:: 71 $
// $Author:: Markd $
// $Date:: 10/22/98 7:57p $
//
// 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.
//
// $Log:: /Quake 2 Engine/Sin/code/game/bullet.cpp $
//
// 71 10/22/98 7:57p Markd
// put in proper pre-caching in all the classes
//
// 70 10/20/98 8:26p Markd
// Added Attacker to DamageSurface stuff
//
// 69 10/13/98 5:27p Markd
// revamped ricochet stuff
//
// 68 10/13/98 12:35p Markd
// Fixed tracers and bullet holes on non-player guys
//
// 67 10/05/98 11:30p Markd
// Added MakeBreakingSound when firing at things
//
// 66 10/04/98 10:36p Markd
// put in ricochet code
//
// 65 9/27/98 3:53p Aldie
// Put in some debugging information
//
// 64 9/18/98 8:14p Markd
// rewrote surface system so that surfaces are now damaged by surface name
// instead of by surfinfo
//
// 63 8/31/98 7:45p Aldie
// Updated surface data structure and removed surfinfo field
//
// 62 8/29/98 9:39p Jimdose
// Added call info to G_Trace
//
// 61 8/29/98 5:27p Markd
// added specialfx, replaced misc with specialfx where appropriate
//
// 60 8/25/98 7:55p Markd
// Fixed weapon angles
//
// 59 8/19/98 6:38p Markd
// Moved Assault rifle tracer into def file
//
// 58 8/14/98 5:37p Aldie
// Moved blood stuff to sentient
//
// 57 8/13/98 8:09p Aldie
// Moved blood particles to armor damage.
//
// 56 8/10/98 6:52p Aldie
// Added scale to bloodsplats
//
// 55 8/06/98 10:53p Aldie
// Added weapon tweaks and kickback. Also modified blast radius damage and
// rocket jumping.
//
// 54 8/04/98 3:27p Aldie
// Revert back to sending PITCH and YAW
//
// 53 8/03/98 3:28p Aldie
// Only send over the PITCH of the gun when firing it
//
// 52 8/01/98 4:39p Aldie
// Put some debug prints
//
// 51 8/01/98 3:24p Aldie
// Added server effects flag for specific weapons
//
// 50 7/31/98 7:42p Aldie
// Client side bullet effects
//
// 49 7/25/98 5:48p Aldie
// Remove shotgun effect
//
// 48 7/24/98 10:03p Aldie
// Fixed bullet damage with invalid traces
//
// 47 7/23/98 6:17p Aldie
// Updated damage system and fixed some damage related bugs. Also put tracers
// back to the way they were, and added gib event to funcscriptmodels
//
// 46 7/22/98 10:41p Aldie
// Fixed tracers
//
// 45 7/21/98 1:10p Aldie
// Added meansofdeath to obituaries
//
// 44 7/17/98 7:57p Markd
// Added radius to FullTrace
//
// 43 7/15/98 9:57p Markd
// Added shields support
//
// 42 6/20/98 7:48p Markd
// using FullTrace now, also checking to make sure we have a valid intersection
// before trying to determine group num etc.
//
// 41 6/19/98 9:29p Jimdose
// Moved gun orientation code to Weapon
//
// 40 6/15/98 10:52p Jimdose
// Disabled fulltrace until bmodels are checked.
//
// 39 6/15/98 10:07p Jimdose
// Made bullet weapons use G_FullTrace
//
// 38 6/11/98 3:34p Jimdose
// TraceAttack was damaging the entity before checking the blood and sparks
// flags, so if the entity died before the check, we got a NULL pointer
// TraceAttack was doing the ricochet trace before checking if it should
// ricochet
//
// 37 6/10/98 2:10p Aldie
// Updated damage function.
//
// 36 6/08/98 11:35a Aldie
// Updated location based damage stuff
//
// 35 6/05/98 6:23p Aldie
// Added location to AddMultiDamage
//
// 34 5/27/98 7:34p Markd
// commented out damage reduction if not hitting body part
//
// 33 5/27/98 5:21p Markd
// fixed up ray intersection a bit
//
// 32 5/27/98 5:02a Markd
// increased nominal multiplier to 0.5f
//
// 31 5/26/98 8:44p Markd
// Put in DamageSkin suport
//
// 30 5/26/98 4:22p Markd
// Working on tri-ray intersection stuff
//
// 29 5/23/98 4:46p Aldie
// Added bulletholes.
//
// 28 5/05/98 7:38p Markd
// Added timeofs to ricochets in bulllet smoke events
//
// 27 5/03/98 8:08p Markd
// Took out old code
//
// 26 5/03/98 4:30p Jimdose
// Changed Vector class
//
// 25 5/02/98 8:41p Markd
// Put in recursive bullet attacks and got rid of ricochets
//
// 24 4/10/98 1:22a Markd
// Added FL_BLOOD support
//
// 23 4/07/98 6:42p Jimdose
// Rewrote weapon code.
// Added order to rank
//
// 22 4/06/98 7:52p Aldie
// Increased range of bullets.
//
// 21 4/04/98 7:31p Jimdose
// Bullets don't spark or ricochet against sky
//
// 20 4/02/98 4:48p Jimdose
// Changed TraceAttack to properly place bloodsplats
//
// 19 3/30/98 2:35p Jimdose
// Moved firing from Magnum to make more general
// Added Ammo
// Added world models
//
// 18 3/27/98 6:34p Jimdose
// Added sparks to show impact of bullets
//
// 17 3/26/98 8:16p Jimdose
// Added precaching of sounds
//
// 16 3/23/98 1:31p Jimdose
// Revamped event and command system
//
// 15 3/05/98 5:44p Aldie
// Support for ricochet flag.
//
// 14 3/04/98 8:02p Aldie
// More support for damage surfaces.
//
// 13 3/04/98 5:12p Aldie
// Added support for damage surfaces.
//
// 12 2/19/98 2:35p Jimdose
// Updated to work with Q2 based progs
//
// 10 12/11/97 3:30p Markd
// Moved SpawnBlood to Weapon
//
// 9 11/18/97 5:28p Markd
// Commented out shotgun
//
// 8 11/11/97 9:41p Markd
// tweaked minimum scale in blood splats
//
// 7 11/11/97 9:38p Markd
// made blood splats be based off of distance as well as damage.
//
// 6 10/31/97 9:02p Jimdose
// Made it so that bsp objects don't leave bloodsplats
//
// 5 10/31/97 7:18p Markd
// Put in BloodSpray
//
// 4 10/31/97 4:28p Jimdose
// Removed redefinition of owner in base class Weapon, so any reference to
// gunoffset through owner had to use type overriding.
//
// 3 10/27/97 3:29p Jimdose
// Removed dependency on quakedef.h
//
// 2 9/26/97 4:43p Jimdose
// Added standard Ritual header
//
// DESCRIPTION:
// Base class for all bullet (hitscan) weapons. Includes definition for shotgun.
//
#include "g_local.h"
#include "specialfx.h"
#include "misc.h"
#include "bullet.h"
#include "q_shared.h"
#include "surface.h"
CLASS_DECLARATION( Weapon, BulletWeapon, NULL );
ResponseDef BulletWeapon::Responses[] =
{
{ NULL, NULL }
};
BulletWeapon::BulletWeapon()
{
modelIndex( "sprites/tracer.spr" );
modelIndex( "sprites/bullethole.spr" );
}
void BulletWeapon::TraceAttack
(
Vector start,
Vector end,
int damage,
trace_t *trace,
int numricochets,
int kick,
int dflags,
int meansofdeath,
qboolean server_effects
)
{
Vector org;
Vector dir;
Vector endpos;
int surfflags;
int surftype;
int timeofs;
Entity *ent;
qboolean ricochet;
if ( HitSky( trace ) )
{
return;
}
ricochet = false;
dir = end - start;
dir.normalize();
org = end - dir;
ent = trace->ent->entity;
if ( !trace->surface )
{
surfflags = 0;
surftype = 0;
}
else
{
surfflags = trace->surface->flags;
surftype = SURFACETYPE_FROM_FLAGS( surfflags );
surfaceManager.DamageSurface( trace, damage, owner );
if ( surfflags & SURF_RICOCHET )
ricochet = true;
}
if ( trace->intersect.valid && ent )
{
//
// see if the parent group has ricochet turned on
//
if ( trace->intersect.parentgroup >= 0 )
{
int flags;
flags = gi.Group_Flags( ent->edict->s.modelindex, trace->intersect.parentgroup );
if ( flags & MDL_GROUP_RICOCHET )
{
surftype = ( flags >> 8 ) & 0xf;
ricochet = true;
}
}
}
if ( ent )
{
if ( !(ent->flags & FL_SHIELDS) )
{
if ( ent->flags & FL_SPARKS )
{
// Take care of ricochet effects on the server
if ( server_effects && !ricochet )
{
timeofs = MAX_RICOCHETS - numricochets;
if ( timeofs > 0xf )
{
timeofs = 0xf;
}
gi.WriteByte( svc_temp_entity );
gi.WriteByte( TE_GUNSHOT );
gi.WritePosition( org.vec3() );
gi.WriteDir( trace->plane.normal );
gi.WriteByte( 0 );
gi.multicast( org.vec3(), MULTICAST_PVS );
}
MadeBreakingSound( org, owner );
}
if ( ent->takedamage )
{
if ( trace->intersect.valid )
{
// We hit a valid group so send in location based damage
ent->Damage( this,
owner,
damage,
trace->endpos,
dir,
trace->plane.normal,
kick,
dflags,
meansofdeath,
trace->intersect.parentgroup,
-1,
trace->intersect.damage_multiplier );
}
else
{
// We didn't hit any groups, so send in generic damage
ent->Damage( this,
owner,
damage,
trace->endpos,
dir,
trace->plane.normal,
kick,
dflags,
meansofdeath,
-1,
-1,
1 );
}
}
}
else
{
surftype = SURF_TYPE_METAL;
ricochet = true;
}
}
if ( ricochet && ( server_effects || ( numricochets < MAX_RICOCHETS ) ) )
{
timeofs = MAX_RICOCHETS - numricochets;
if ( timeofs > 0xf )
{
timeofs = 0xf;
}
gi.WriteByte( svc_temp_entity );
gi.WriteByte( TE_GUNSHOT );
gi.WritePosition( org.vec3() );
gi.WriteDir( trace->plane.normal );
gi.WriteByte( timeofs );
gi.multicast( org.vec3(), MULTICAST_PVS );
}
if (
ricochet &&
numricochets &&
damage
)
{
dir += Vector( trace->plane.normal ) * 2;
endpos = org + dir * 8192;
//
// since this is a ricochet, we don't ignore the wewapon owner this time.
//
*trace = G_FullTrace( org, vec_zero, vec_zero, endpos, 5, NULL, MASK_SHOT, "BulletWeapon::TraceAttack" );
if ( trace->fraction != 1.0 )
{
endpos = trace->endpos;
TraceAttack( org, endpos, damage * 0.8f, trace, numricochets - 1, kick, dflags, meansofdeath, true );
}
}
}
void BulletWeapon::FireBullets
(
int numbullets,
Vector spread,
int mindamage,
int maxdamage,
int dflags,
int meansofdeath,
qboolean server_effects
)
{
Vector src;
Vector dir;
Vector end;
trace_t trace;
Vector right;
Vector up;
int i;
assert( owner );
if ( !owner )
{
return;
}
GetMuzzlePosition( &src, &dir );
owner->angles.AngleVectors( NULL, &right, &up );
angles = dir.toAngles();
setAngles( angles );
for( i = 0; i < numbullets; i++ )
{
end = src +
dir * 8192 +
right * G_CRandom() * spread.x +
up * G_CRandom() * spread.y;
trace = G_FullTrace( src, vec_zero, vec_zero, end, 5, owner, MASK_SHOT, "BulletWeapon::FireBullets" );
#if 0
Com_Printf("Server OWNER Angles:%0.2f %0.2f %0.2f\n",owner->angles[0],owner->angles[1],owner->angles[2]);
Com_Printf("Server Bullet Angles:%0.2f %0.2f %0.2f\n",angles[0],angles[1],angles[2]);
Com_Printf("Right :%0.2f %0.2f %0.2f\n",right[0],right[1],right[2]);
Com_Printf("Up :%0.2f %0.2f %0.2f\n",up[0],up[1],up[2]);
Com_Printf("Direction :%0.2f %0.2f %0.2f\n",dir[0],dir[1],dir[2]);
Com_Printf("Endpoint :%0.2f %0.2f %0.2f\n",end[0],end[1],end[2]);
Com_Printf("Server Trace Start :%0.2f %0.2f %0.2f\n",src[0],src[1],src[2]);
Com_Printf("Server Trace End :%0.2f %0.2f %0.2f\n",trace.endpos[0],trace.endpos[1],trace.endpos[2]);
Com_Printf("\n");
#endif
if ( trace.fraction != 1.0 )
{
TraceAttack( src, trace.endpos, mindamage + (int)G_Random( maxdamage - mindamage + 1 ), &trace, MAX_RICOCHETS, kick, dflags, meansofdeath, server_effects );
}
}
}
void BulletWeapon::FireTracer( void )
{
Entity *tracer;
Vector src,dir,end;
trace_t trace;
GetMuzzlePosition( &src, &dir );
end = src + dir * 8192;
trace = G_Trace( src, vec_zero, vec_zero, end, owner, MASK_SHOT, "BulletWeapon::FireTracer" );
tracer = new Entity;
tracer->angles = dir.toAngles();
tracer->angles[ PITCH ] = -tracer->angles[ PITCH ] + 90;
//tracer->angles[PITCH] *= -1;
tracer->setAngles( tracer->angles );
tracer->setMoveType( MOVETYPE_NONE );
tracer->setSolidType( SOLID_NOT );
tracer->setModel( "sprites/tracer.spr" );
tracer->setSize( "0 0 0", "0 0 0" );
tracer->setOrigin( trace.endpos );
tracer->edict->s.renderfx &= ~RF_FRAMELERP;
VectorCopy( src, tracer->edict->s.old_origin );
tracer->PostEvent(EV_Remove,0.1f);
}