2011-06-01 12:20:56 +00:00
// Copyright (C) 1999-2000 Id Software, Inc.
//
// cg_weapons.c -- events and effects dealing with weapons
# include "cg_local.h"
# include "fx_local.h"
//RPG-X : TiM - Weapons Arrays
static int RAweapons [ 8 ] = { WP_PADD ,
WP_TRICORDER ,
WP_COMPRESSION_RIFLE ,
WP_TR116 ,
WP_VOYAGER_HYPO ,
WP_DERMAL_REGEN ,
WP_MEDKIT ,
WP_COFFEE
} ;
static char * RAweapFileName [ 8 ] = { " padd " ,
" tricorder " ,
" prifle " ,
" tr116 " ,
" hypospray " ,
" dermal_regen " ,
" medkit " ,
" coffeecup "
} ;
/*
= = = = = = = = = = = = = = = = =
CG_RegisterWeapon
The server says this item is used on this level
= = = = = = = = = = = = = = = = =
*/
// kef -- sad? yep.
typedef struct wpnBarrelInfo_s
{
weapon_t giTag ;
int numBarrels ;
int flashTime ;
} wpnBarrelInfo_t ;
wpnBarrelInfo_t wpnBarrelData [ ] =
{
{ WP_NULL_HAND , 0 , 0 } ,
{ WP_TRICORDER , 0 , 0 } ,
{ WP_PADD , 0 , 0 } ,
{ WP_COFFEE , 0 , 0 } ,
{ WP_PHASER , 0 , 0 } ,
{ WP_COMPRESSION_RIFLE , 0 , 120 } ,
{ WP_TR116 , 1 , 60 } ,
{ WP_GRENADE_LAUNCHER , 2 , 150 } ,
{ WP_QUANTUM_BURST , 1 , 200 } ,
{ WP_DISRUPTOR , 1 , 130 } ,
{ WP_MEDKIT , 0 , 0 } ,
{ WP_VOYAGER_HYPO , 0 , 0 } ,
{ WP_DERMAL_REGEN , 0 , 0 } ,
{ WP_TOOLKIT , 0 , 0 } ,
{ WP_HYPERSPANNER , 0 , 0 } ,
// make sure this is the last entry in this array, please
{ WP_NONE , 0 , 0 } ,
} ;
//wpnBarrelInfo_t wpnBarrelData[] =
//{
// {WP_PHASER, 0, 0},
// {WP_COMPRESSION_RIFLE, 0, 100},
// {WP_NULL_HAND, 0, 0},
// {WP_COFFEE, 0, 0},
// {WP_DISRUPTOR, 1, 80},
// {WP_GRENADE_LAUNCHER, 2, 140},
// {WP_TR116, 1, 120},
// {WP_QUANTUM_BURST, 1, 200},
// {WP_DERMAL_REGEN, 0, 0},
// {WP_VOYAGER_HYPO, 0, 0},
// {WP_TOOLKIT, 0, 0},
// {WP_MEDKIT, 0, 0},
// {WP_TRICORDER, 0, 0},
// {WP_PADD, 0, 0},
// {WP_NEUTRINO_PROBE, 0, 0},
// {WP_TR116, 0, 90},
//
// // make sure this is the last entry in this array, please
// {WP_NONE, 0},
//};
void CG_RegisterWeapon ( int weaponNum ) {
weaponInfo_t * weaponInfo ;
gitem_t * item , * ammo ;
char path [ MAX_QPATH ] ;
vec3_t mins , maxs ;
int i ;
int numBarrels = 0 ;
wpnBarrelInfo_t * barrelInfo = NULL ;
weaponInfo = & cg_weapons [ weaponNum ] ;
if ( weaponNum = = 0 ) {
return ;
}
if ( weaponInfo - > registered ) {
return ;
}
memset ( weaponInfo , 0 , sizeof ( * weaponInfo ) ) ;
weaponInfo - > registered = qtrue ;
for ( item = bg_itemlist + 1 ; item - > classname ; item + + ) {
if ( item - > giType = = IT_WEAPON & & item - > giTag = = weaponNum ) {
/*if ( weaponNum == WP_DISRUPTOR ) {
Com_Printf ( S_COLOR_RED " Registering %s with pickup name of %s \n " , bg_itemlist [ 10 ] . classname , bg_itemlist [ 10 ] . pickup_name ) ;
} */
weaponInfo - > item = item ;
break ;
}
}
if ( ! item - > classname ) {
CG_Error ( " Couldn't find weapon %i " , weaponNum ) ;
}
CG_RegisterItemVisuals ( item - bg_itemlist ) ;
weaponInfo - > weaponModel = trap_R_RegisterModel ( item - > world_model ) ;
// kef -- load in-view model
weaponInfo - > viewModel = trap_R_RegisterModel ( item - > view_model ) ;
// calc midpoint for rotation
trap_R_ModelBounds ( weaponInfo - > weaponModel , mins , maxs ) ;
for ( i = 0 ; i < 3 ; i + + ) {
weaponInfo - > weaponMidpoint [ i ] = mins [ i ] + 0.5 * ( maxs [ i ] - mins [ i ] ) ;
}
weaponInfo - > weaponIcon = trap_R_RegisterShader ( item - > icon ) ;
for ( ammo = bg_itemlist + 1 ; ammo - > classname ; ammo + + ) {
if ( ammo - > giType = = IT_AMMO & & ammo - > giTag = = weaponNum ) {
break ;
}
}
// if ( ammo->classname && ammo->world_model ) {
// weaponInfo->ammoModel = trap_R_RegisterModel( ammo->world_model );
// }
strcpy ( path , item - > view_model ) ;
COM_StripExtension ( path , path ) ;
strcat ( path , " _flash.md3 " ) ;
weaponInfo - > flashModel = trap_R_RegisterModel ( path ) ;
for ( barrelInfo = wpnBarrelData ; barrelInfo - > giTag ! = WP_NONE ; barrelInfo + + )
{
if ( barrelInfo - > giTag = = weaponNum )
{
numBarrels = barrelInfo - > numBarrels ;
break ;
}
}
for ( i = 0 ; i < numBarrels ; i + + ) {
Q_strncpyz ( path , item - > view_model , MAX_QPATH ) ;
COM_StripExtension ( path , path ) ;
if ( i )
{
strcat ( path , va ( " _barrel%d.md3 " , i + 1 ) ) ;
}
else
strcat ( path , " _barrel.md3 " ) ;
weaponInfo - > barrelModel [ i ] = trap_R_RegisterModel ( path ) ;
}
strcpy ( path , item - > view_model ) ;
COM_StripExtension ( path , path ) ;
strcat ( path , " _hand.md3 " ) ;
weaponInfo - > handsModel = trap_R_RegisterModel ( path ) ;
if ( ! weaponInfo - > handsModel ) {
weaponInfo - > handsModel = trap_R_RegisterModel ( " models/weapons2/prifle/prifle_hand.md3 " ) ;
}
switch ( weaponNum ) {
case WP_PHASER :
MAKERGB ( weaponInfo - > flashDlightColor , 0 , 0 , 0 ) ;
weaponInfo - > firingSound = trap_S_RegisterSound ( SOUND_DIR " phaser/phaserfiring.wav " ) ;
weaponInfo - > altFiringSound = trap_S_RegisterSound ( SOUND_DIR " phaser/altphaserfiring.wav " ) ;
weaponInfo - > flashSound = trap_S_RegisterSound ( SOUND_DIR " phaser/phaserstart.wav " ) ;
weaponInfo - > altFlashSnd = trap_S_RegisterSound ( SOUND_DIR " phaser/altphaserstart.wav " ) ;
weaponInfo - > stopSound = trap_S_RegisterSound ( SOUND_DIR " phaser/phaserstop.wav " ) ;
weaponInfo - > altStopSound = trap_S_RegisterSound ( SOUND_DIR " phaser/altphaserstop.wav " ) ;
cgs . media . phaserShader = trap_R_RegisterShader ( " gfx/misc/phaser_stx " ) ;
cgs . media . phaserEmptyShader = trap_R_RegisterShader ( " gfx/misc/phaserempty " ) ;
cgs . media . phaserAltShader = trap_R_RegisterShader ( " gfx/effects/whitelaser " ) ; // "gfx/misc/phaser_alt" );
cgs . media . phaserAltEmptyShader = trap_R_RegisterShader ( " gfx/misc/phaser_altempty " ) ;
cgs . media . phaserMuzzleEmptyShader = trap_R_RegisterShader ( " models/weapons2/phaser/muzzle_empty " ) ;
break ;
case WP_DERMAL_REGEN :
weaponInfo - > firingSound = trap_S_RegisterSound ( SOUND_DIR " dermal_regen/dm_1.wav " ) ;
weaponInfo - > altFiringSound = trap_S_RegisterSound ( SOUND_DIR " dermal_regen/dm_2.wav " ) ;
break ;
case WP_DISRUPTOR :
//weaponInfo->missileTrailFunc = FX_StasisProjectileThink;
weaponInfo - > missileModel = trap_R_RegisterModel ( " models/weapons2/alien_disruptor/disruptor_bolt.md3 " ) ;
weaponInfo - > missileDlight = 70 ;
MAKERGB ( weaponInfo - > missileDlightColor , 0.0 , 1.0 , 0.0 ) ;
MAKERGB ( weaponInfo - > flashDlightColor , 0.0 , 1.0 , 0.0 ) ;
weaponInfo - > altFlashSnd = trap_S_RegisterSound ( SOUND_DIR " alien_disruptor/fire.wav " ) ;
weaponInfo - > mainHitSound = trap_S_RegisterSound ( SOUND_DIR " stasis/hit_wall.wav " ) ;
weaponInfo - > flashSound = trap_S_RegisterSound ( SOUND_DIR " alien_disruptor/disruptorstart.wav " ) ;
weaponInfo - > stopSound = trap_S_RegisterSound ( SOUND_DIR " alien_disruptor/disruptorstop.wav " ) ;
weaponInfo - > firingSound = trap_S_RegisterSound ( SOUND_DIR " alien_disruptor/disruptorfiring.wav " ) ;
cgs . media . disruptorBolt = trap_R_RegisterShader ( " gfx/misc/disruptor_bolt " ) ;
cgs . media . disruptorStreak = trap_R_RegisterShader ( " gfx/misc/disruptor_streak " ) ;
//cgs.media.altIMOD2Shader = trap_R_RegisterShader( "gfx/misc/IMOD2alt" );
//cgs.media.dnBoltShader = trap_R_RegisterShader( "gfx/misc/dnBolt" );
cgs . media . greenParticleShader = trap_R_RegisterShader ( " gfx/misc/greenparticle " ) ;
cgs . media . greenParticleStreakShader = trap_R_RegisterShader ( " gfx/misc/greenparticle_anamorphic " ) ;
cgs . media . disruptorBeam = trap_R_RegisterShader ( " gfx/misc/disruptor " ) ;
break ;
case WP_GRENADE_LAUNCHER :
weaponInfo - > missileModel = trap_R_RegisterModel ( " models/weapons2/launcher/projectile.md3 " ) ;
if ( rpg_ctribgrenade . integer = = 1 ) //RPG-X: - RedTechie Possible Hack! FIX | TiM: Heh, you're a possible hack :)
{
weaponInfo - > alt_missileModel = trap_R_RegisterModel ( " models/weapons2/launcher/projectile2a.md3 " ) ;
weaponInfo - > altFlashSnd = trap_S_RegisterSound ( SOUND_DIR " glauncher/alt_fire.wav " ) ;
weaponInfo - > altHitSound = trap_S_RegisterSound ( " sound/weapons/glauncher/beepa.wav " ) ;
cgs . media . grenadeAltStickSound = trap_S_RegisterSound ( SOUND_DIR " glauncher/alt_stick.wav " ) ;
}
else
{
weaponInfo - > alt_missileModel = trap_R_RegisterModel ( " models/weapons2/launcher/projectile2.md3 " ) ;
weaponInfo - > altFlashSnd = trap_S_RegisterSound ( SOUND_DIR " glauncher/alt_fire.wav " ) ;
weaponInfo - > altHitSound = trap_S_RegisterSound ( SOUND_DIR " glauncher/beep.wav " ) ;
cgs . media . grenadeAltStickSound = trap_S_RegisterSound ( SOUND_DIR " glauncher/alt_stick.wav " ) ;
}
weaponInfo - > missileTrailFunc = FX_GrenadeThink ;
//TiM : No flash anymore
MAKERGB ( weaponInfo - > flashDlightColor , 0.0 , 0.0 , 0.0 ) ;
//MAKERGB( weaponInfo->flashDlightColor, 0.6, 0.6, 1 );
weaponInfo - > flashSound = trap_S_RegisterSound ( SOUND_DIR " glauncher/fire.wav " ) ;
cgs . media . grenadeBounceSound1 = trap_S_RegisterSound ( SOUND_DIR " glauncher/bounce1.wav " ) ;
cgs . media . grenadeBounceSound2 = trap_S_RegisterSound ( SOUND_DIR " glauncher/bounce2.wav " ) ;
cgs . media . grenadeExplodeSound = trap_S_RegisterSound ( SOUND_DIR " glauncher/explode.wav " ) ;
cgs . media . grenadeAltExplodeSnd = trap_S_RegisterSound ( SOUND_DIR " glauncher/alt_explode.wav " ) ;
cgs . media . orangeTrailShader = trap_R_RegisterShader ( " gfx/misc/orangetrail " ) ;
cgs . media . compressionMarkShader = trap_R_RegisterShader ( " gfx/damage/burnmark1 " ) ;
cgs . media . whiteLaserShader = trap_R_RegisterShader ( " gfx/effects/whitelaser " ) ;
cgs . media . borgEyeFlareShader = trap_R_RegisterShader ( " gfx/misc/borgeyeflare " ) ;
break ;
case WP_COFFEE :
//MAKERGB( weaponInfo->flashDlightColor, 1, 0.6, 0.6 );
/*weaponInfo->flashSound = trap_S_RegisterSound( SOUND_DIR "scavenger/fire.wav" );
weaponInfo - > altFlashSnd = trap_S_RegisterSound ( SOUND_DIR " scavenger/alt_fire.wav " ) ;
weaponInfo - > mainHitSound = trap_S_RegisterSound ( SOUND_DIR " scavenger/hit_wall.wav " ) ;
weaponInfo - > altHitSound = trap_S_RegisterSound ( SOUND_DIR " scavenger/alt_explode.wav " ) ;
weaponInfo - > missileTrailFunc = FX_ScavengerProjectileThink ;
weaponInfo - > alt_missileTrailFunc = FX_ScavengerAltFireThink ;
// weaponInfo->wiTrailTime = 100;
// weaponInfo->trailRadius = 8;
cgs . media . tetrionFlareShader = trap_R_RegisterShader ( " gfx/misc/tet1 " ) ;
cgs . media . tetrionTrail2Shader = trap_R_RegisterShader ( " gfx/misc/trail2 " ) ;
cgs . media . redFlareShader = trap_R_RegisterShader ( " gfx/misc/red_flare " ) ;
cgs . media . scavengerAltShader = trap_R_RegisterShader ( " gfx/misc/scavaltfire " ) ;
cgs . media . scavExplosionFastShader = trap_R_RegisterShader ( " scavExplosionFast " ) ;
cgs . media . scavExplosionSlowShader = trap_R_RegisterShader ( " scavExplosionSlow " ) ;
cgs . media . compressionMarkShader = trap_R_RegisterShader ( " gfx/damage/burnmark1 " ) ; */
break ;
case WP_QUANTUM_BURST :
MAKERGB ( weaponInfo - > flashDlightColor , 0.6 , 0.6 , 1 ) ; //Bluish
weaponInfo - > missileTrailFunc = FX_QuantumThink ;
weaponInfo - > alt_missileTrailFunc = FX_QuantumAltThink ;
weaponInfo - > missileDlight = 75 ;
weaponInfo - > alt_missileDlight = 100 ;
MAKERGB ( weaponInfo - > missileDlightColor , 1.0 , 1.0 , 0.5 ) ; //yellowish
weaponInfo - > flashSound = trap_S_RegisterSound ( SOUND_DIR " quantum/fire.wav " ) ;
weaponInfo - > altFlashSnd = trap_S_RegisterSound ( SOUND_DIR " quantum/alt_fire.wav " ) ;
weaponInfo - > mainHitSound = trap_S_RegisterSound ( SOUND_DIR " quantum/hit_wall.wav " ) ; ;
weaponInfo - > altHitSound = trap_S_RegisterSound ( SOUND_DIR " quantum/alt_hit_wall.wav " ) ; ;
cgs . media . whiteRingShader = trap_R_RegisterShader ( " gfx/misc/whitering " ) ;
cgs . media . orangeRingShader = trap_R_RegisterShader ( " gfx/misc/orangering " ) ;
cgs . media . quantumExplosionShader = trap_R_RegisterShader ( " quantumExplosion " ) ;
cgs . media . quantumFlashShader = trap_R_RegisterShader ( " yellowflash " ) ;
//cgs.media.bigBoomShader = trap_R_RegisterShader( "gfx/misc/bigboom" );
cgs . media . orangeTrailShader = trap_R_RegisterShader ( " gfx/misc/orangetrail " ) ;
cgs . media . compressionMarkShader = trap_R_RegisterShader ( " gfx/damage/burnmark1 " ) ;
cgs . media . orangeTrailShader = trap_R_RegisterShader ( " gfx/misc/orangetrail " ) ;
cgs . media . quantumRingShader = trap_R_RegisterShader ( " gfx/misc/detpack3 " ) ;
cgs . media . quantumBoom = trap_S_RegisterSound ( SOUND_DIR " explosions/explode5.wav " ) ;
break ;
case WP_NULL_HAND :
/*MAKERGB( weaponInfo->flashDlightColor, 0.6, 0.6, 1 );
weaponInfo - > flashSound = trap_S_RegisterSound ( SOUND_DIR " IMOD/fire.wav " ) ;
weaponInfo - > altFlashSnd = trap_S_RegisterSound ( SOUND_DIR " IMOD/alt_fire.wav " ) ;
cgs . media . IMODShader = trap_R_RegisterShader ( " gfx/misc/IMOD " ) ;
cgs . media . IMOD2Shader = trap_R_RegisterShader ( " gfx/misc/IMOD2 " ) ;
cgs . media . altIMODShader = trap_R_RegisterShader ( " gfx/misc/IMODalt " ) ;
cgs . media . altIMOD2Shader = trap_R_RegisterShader ( " gfx/misc/IMOD2alt " ) ;
cgs . media . imodExplosionShader = trap_R_RegisterShader ( " imodExplosion " ) ; */
break ;
case WP_COMPRESSION_RIFLE :
if ( ! grp_berp . integer ) {
MAKERGB ( weaponInfo - > flashDlightColor , 0.59 , 0.24 , 0.25 ) ;
MAKERGB ( weaponInfo - > missileDlightColor , 0.59 , 0.24 , 0.25 ) ;
} else {
MAKERGB ( weaponInfo - > flashDlightColor , 0.16 , 0.32 , 0.5 ) ;
MAKERGB ( weaponInfo - > missileDlightColor , 0.16 , 0.32 , 0.5 ) ;
}
weaponInfo - > missileModel = trap_R_RegisterModel ( " models/weapons2/prifle/prifle_bolt.md3 " ) ;
weaponInfo - > missileDlight = 90 ;
weaponInfo - > flashSound = trap_S_RegisterSound ( SOUND_DIR " prifle/fire.wav " ) ;
weaponInfo - > altFlashSnd = trap_S_RegisterSound ( SOUND_DIR " prifle/phaserriflestart.wav " ) ;
weaponInfo - > altStopSound = trap_S_RegisterSound ( SOUND_DIR " prifle/phaserriflestop.wav " ) ;
weaponInfo - > altFiringSound = trap_S_RegisterSound ( SOUND_DIR " prifle/phaserriflefiring.wav " ) ;
weaponInfo - > mainHitSound = trap_S_RegisterSound ( SOUND_DIR " prifle/impact.wav " ) ; ;
cgs . media . prifleImpactShader = trap_R_RegisterShader ( " gfx/effects/prifle_hit " ) ;
cgs . media . compressionAltBeamShader = trap_R_RegisterShader ( " gfx/effects/prifle_altbeam " ) ;
cgs . media . compressionAltBlastShader = trap_R_RegisterShader ( " gfx/effects/prifle_altblast " ) ;
cgs . media . compressionMarkShader = trap_R_RegisterShader ( " gfx/damage/burnmark1 " ) ;
cgs . media . prifleBolt = trap_R_RegisterShader ( " gfx/misc/priflebolt " ) ;
cgs . media . liteRedParticleStreakShader = trap_R_RegisterShader ( " gfx/misc/literedparticle_anamorphic " ) ;
cgs . media . liteRedParticleShader = trap_R_RegisterShader ( " gfx/misc/literedparticle " ) ;
cgs . media . flashlightModel = trap_R_RegisterModel ( " models/weapons2/prifle/prifle_flashlight.md3 " ) ; //RPG-X : TiM - flashlight model
cgs . media . prifleBeam = trap_R_RegisterShader ( " gfx/misc/phaser_rifle " ) ;
break ;
/* case WP_TR116:
MAKERGB ( weaponInfo - > flashDlightColor , 0.16 , 0.16 , 1 ) ;
weaponInfo - > flashSound = trap_S_RegisterSound ( " sound/weapons/hitonhead.wav " ) ;
weaponInfo - > altFlashSnd = trap_S_RegisterSound ( " sound/weapons/guncharge.wav " ) ;
cgs . media . tetrionTrail2Shader = trap_R_RegisterShader ( " gfx/misc/trail2 " ) ;
cgs . media . compressionMarkShader = trap_R_RegisterShader ( " gfx/damage/burnmark1 " ) ;
weaponInfo - > mainHitSound = trap_S_RegisterSound ( SOUND_DIR " prifle/impact.wav " ) ;
break ; */
/*
case WP_TR116 : //OLD CODE (replaced for TR116)
MAKERGB ( weaponInfo - > flashDlightColor , 0.6 , 0.6 , 1 ) ;
weaponInfo - > flashSound = trap_S_RegisterSound ( SOUND_DIR " tetrion/fire.wav " ) ;
weaponInfo - > altFlashSnd = trap_S_RegisterSound ( SOUND_DIR " tetrion/alt_fire.wav " ) ;
cgs . media . tetrionRicochetSound1 = trap_S_RegisterSound ( SOUND_DIR " tetrion/ricochet1.wav " ) ;
cgs . media . tetrionRicochetSound2 = trap_S_RegisterSound ( SOUND_DIR " tetrion/ricochet2.wav " ) ;
cgs . media . tetrionRicochetSound3 = trap_S_RegisterSound ( SOUND_DIR " tetrion/ricochet3.wav " ) ;
weaponInfo - > missileTrailFunc = FX_TetrionProjectileThink ;
weaponInfo - > alt_missileTrailFunc = FX_TetrionProjectileThink ;
cgs . media . greenBurstShader = trap_R_RegisterShader ( " gfx/misc/greenburst " ) ;
cgs . media . greenTrailShader = trap_R_RegisterShader ( " gfx/misc/greentrail " ) ;
cgs . media . tetrionTrail2Shader = trap_R_RegisterShader ( " gfx/misc/trail2 " ) ;
cgs . media . tetrionFlareShader = trap_R_RegisterShader ( " gfx/misc/tet1 " ) ;
cgs . media . borgFlareShader = trap_R_RegisterShader ( " gfx/misc/borgflare " ) ;
cgs . media . bulletmarksShader = trap_R_RegisterShader ( " textures/decals/bulletmark4 " ) ;
break ;
*/
case WP_VOYAGER_HYPO :
weaponInfo - > flashSound = weaponInfo - > altFlashSnd = trap_S_RegisterSound ( " sound/items/jetpuffmed.wav " ) ;
break ;
case WP_TRICORDER :
weaponInfo - > firingSound = trap_S_RegisterSound ( " sound/items/tricorderscan.wav " ) ; //altFlashSnd
weaponInfo - > altFiringSound = trap_S_RegisterSound ( " sound/ambience/voyager/medictricorder.wav " ) ; //flashSound
//weaponInfo->isAnimSndBased = qtrue;
break ;
case WP_PADD :
weaponInfo - > firingSound = trap_S_RegisterSound ( SOUND_DIR " padd/padd_1.wav " ) ; //flashSound
weaponInfo - > altFiringSound = trap_S_RegisterSound ( SOUND_DIR " padd/padd_2.wav " ) ; //altFlashSnd
weaponInfo - > isAnimSndBased = qtrue ;
break ;
case WP_HYPERSPANNER :
weaponInfo - > firingSound = trap_S_RegisterSound ( SOUND_DIR " hyperspanner/spanner_1.wav " ) ;
weaponInfo - > altFiringSound = trap_S_RegisterSound ( SOUND_DIR " hyperspanner/spanner_2.wav " ) ;
break ;
case WP_TR116 :
weaponInfo - > flashSound = trap_S_RegisterSound ( SOUND_DIR " hitonhead.wav " ) ;
weaponInfo - > altFlashSnd = weaponInfo - > flashSound ;
//weaponInfo->altFlashSnd = trap_S_RegisterSound( "sound/weapons/guncharge.wav" );
break ;
//Toolkit
case WP_TOOLKIT :
weaponInfo - > flashSound = trap_S_RegisterSound ( SOUND_DIR " toolkit/toolkit_1.wav " ) ;
weaponInfo - > altFlashSnd = trap_S_RegisterSound ( SOUND_DIR " toolkit/toolkit_2.wav " ) ;
break ;
//Medkit
case WP_MEDKIT :
weaponInfo - > flashSound = trap_S_RegisterSound ( SOUND_DIR " medkit/medkit_1.wav " ) ;
weaponInfo - > altFlashSnd = trap_S_RegisterSound ( SOUND_DIR " medkit/medkit_2.wav " ) ;
break ;
default :
MAKERGB ( weaponInfo - > flashDlightColor , 1 , 1 , 1 ) ;
weaponInfo - > flashSound = trap_S_RegisterSound ( SOUND_DIR " prifle/fire.wav " ) ;
break ;
}
}
/*
= = = = = = = = = = = = = = = = =
CG_RegisterItemVisuals
The server says this item is used on this level
= = = = = = = = = = = = = = = = =
*/
void CG_RegisterItemVisuals ( int itemNum ) {
itemInfo_t * itemInfo ;
gitem_t * item ;
itemInfo = & cg_items [ itemNum ] ;
if ( itemInfo - > registered ) {
return ;
}
item = & bg_itemlist [ itemNum ] ;
memset ( itemInfo , 0 , sizeof ( & itemInfo ) ) ;
itemInfo - > registered = qtrue ;
itemInfo - > model = trap_R_RegisterModel ( item - > world_model ) ;
itemInfo - > icon = trap_R_RegisterShader ( item - > icon ) ;
if ( item - > giType = = IT_WEAPON ) {
CG_RegisterWeapon ( item - > giTag ) ;
}
// since the seeker uses the scavenger rifes sounds, we must precache the scavenger rifle stuff if we hit the item seeker
/* if ( item->giTag == PW_FLASHLIGHT)
{
CG_RegisterWeapon ( WP_COFFEE ) ;
} */
// hang onto the handles for holdable items in case they're useable (e.g. detpack)
/* if (IT_HOLDABLE == item->giType)
{
// sanity check
if ( ( item - > giTag < HI_NUM_HOLDABLE ) & & ( item - > giTag > 0 ) ) // use "> 0" cuz first slot should be empty
{
if ( item - > world_model [ 1 ] )
{
cgs . useableModels [ item - > giTag ] = trap_R_RegisterModel ( item - > useablemodel ) ;
}
else
{
cgs . useableModels [ item - > giTag ] = itemInfo - > model ] ;
}
}
}
*/
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
VIEW WEAPON
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = =
CG_MapTorsoToWeaponFrame
= = = = = = = = = = = = = = = = =
*/
static int CG_MapTorsoToWeaponFrame ( clientInfo_t * ci , int frame ) {
animation_t * anim ;
// change weapon
anim = & cg_animsList [ ci - > animIndex ] . animations [ TORSO_DROPWEAP1 ] ;
if ( frame > = anim - > firstFrame
& & frame < anim - > firstFrame + 9 ) {
return frame - anim - > firstFrame + 6 ;
}
// stand attack
anim = & cg_animsList [ ci - > animIndex ] . animations [ BOTH_ATTACK3 ] ;
if ( frame > = anim - > firstFrame & & frame < anim - > firstFrame + 6 ) {
return 1 + frame - anim - > firstFrame ;
}
// stand attack 2
anim = & cg_animsList [ ci - > animIndex ] . animations [ BOTH_ATTACK2 ] ;
if ( frame > = anim - > firstFrame & & frame < anim - > firstFrame + 6 ) {
return 1 + frame - anim - > firstFrame ;
}
anim = & cg_animsList [ ci - > animIndex ] . animations [ TORSO_WEAPONREADY1 ] ;
if ( frame > = anim - > firstFrame & & frame < anim - > firstFrame + 6 ) {
return 1 + frame - anim - > firstFrame ;
}
// change weapon
//USED TO BE TORSO_RAISE
/* if ( frame >= ci->animations[TORSO_DROPWEAP1].firstFrame
& & frame < ci - > animations [ TORSO_DROPWEAP1 ] . firstFrame + 9 ) {
return frame - ci - > animations [ TORSO_DROPWEAP1 ] . firstFrame + 6 ;
}
// stand attack
if ( frame > = ci - > animations [ BOTH_ATTACK3 ] . firstFrame
& & frame < ci - > animations [ BOTH_ATTACK3 ] . firstFrame + 6 ) {
return 1 + frame - ci - > animations [ BOTH_ATTACK3 ] . firstFrame ;
}
// stand attack 2
if ( frame > = ci - > animations [ BOTH_ATTACK2 ] . firstFrame
& & frame < ci - > animations [ BOTH_ATTACK2 ] . firstFrame + 6 ) {
return 1 + frame - ci - > animations [ BOTH_ATTACK2 ] . firstFrame ;
} */
return 0 ;
}
/*
= = = = = = = = = = = = = =
CG_CalculateWeaponPosition
= = = = = = = = = = = = = =
*/
//BOOKMARK
static void CG_CalculateWeaponPosition ( vec3_t origin , vec3_t angles ) {
float scale ;
int delta ;
float fracsin ;
VectorCopy ( cg . refdef . vieworg , origin ) ;
VectorCopy ( cg . refdefViewAngles , angles ) ;
// on odd legs, invert some angles
if ( cg . bobcycle & 1 ) {
scale = - cg . xyspeed ;
} else {
scale = cg . xyspeed ;
}
// gun angles from bobbing
angles [ ROLL ] + = scale * cg . bobfracsin * 0.005 ;
angles [ YAW ] + = scale * cg . bobfracsin * 0.01 ;
angles [ PITCH ] + = cg . xyspeed * cg . bobfracsin * 0.005 ;
// drop the weapon when landing
delta = cg . time - cg . landTime ;
if ( delta < LAND_DEFLECT_TIME ) {
origin [ 2 ] + = cg . landChange * 0.25 * delta / LAND_DEFLECT_TIME ;
} else if ( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME ) {
origin [ 2 ] + = cg . landChange * 0.25 *
( LAND_DEFLECT_TIME + LAND_RETURN_TIME - delta ) / LAND_RETURN_TIME ;
}
#if 0
// drop the weapon when stair climbing
delta = cg . time - cg . stepTime ;
if ( delta < STEP_TIME / 2 ) {
origin [ 2 ] - = cg . stepChange * 0.25 * delta / ( STEP_TIME / 2 ) ;
} else if ( delta < STEP_TIME ) {
origin [ 2 ] - = cg . stepChange * 0.25 * ( STEP_TIME - delta ) / ( STEP_TIME / 2 ) ;
}
# endif
// idle drift
scale = cg . xyspeed + 40 ;
fracsin = sin ( cg . time * 0.001 ) ;
angles [ ROLL ] + = scale * fracsin * 0.01 ;
angles [ YAW ] + = scale * fracsin * 0.01 ;
angles [ PITCH ] + = scale * fracsin * 0.01 ;
}
/*
= = = = = = = = = = = = = = =
CG_LightningBolt
Origin will be the exact tag point , which is slightly
different than the muzzle point used for determining hits .
The cent should be the non - predicted cent if it is from the player ,
so the endpoint will reflect the simulated strike ( lagging the predicted
angle )
= = = = = = = = = = = = = = =
*/
# define RANGE_BEAM (2048.0)
# define BEAM_VARIATION 6
void CG_LightningBolt ( centity_t * cent , vec3_t origin )
{
trace_t trace ;
// gentity_t *traceEnt;
vec3_t startpos , endpos , forward ;
qboolean spark = qfalse , impact = qtrue ;
if ( cg . snap - > ps . pm_type = = PM_INTERMISSION )
{
return ; // Don't draw a phaser during an intermission you crezzy mon!
}
//Must be a durational weapon
if ( cent - > currentState . clientNum = = cg . snap - > ps . clientNum & & ! cg . renderingThirdPerson & & ! ( cent - > currentState . eFlags & EF_ITEMPLACEHOLDER ) ) //fuck decoys
{
// different checks for first person view
if ( cg . snap - > ps . weapon = = WP_HYPERSPANNER | |
cg . snap - > ps . weapon = = WP_PHASER | |
cg . snap - > ps . weapon = = WP_DERMAL_REGEN | |
( cg . snap - > ps . eFlags & EF_ALT_FIRING & & cg . snap - > ps . weapon = = WP_COMPRESSION_RIFLE )
| | ( ! ( cg . snap - > ps . eFlags & EF_ALT_FIRING ) & & cg . snap - > ps . weapon = = WP_DISRUPTOR )
)
{ /*continue*/ }
else
return ;
} else {
if ( cent - > currentState . weapon = = WP_HYPERSPANNER | |
cent - > currentState . weapon = = WP_PHASER | |
cent - > currentState . weapon = = WP_DERMAL_REGEN | |
( cent - > currentState . eFlags & EF_ALT_FIRING & & ( cent - > currentState . weapon = = WP_COMPRESSION_RIFLE ) ) | |
( ! ( cent - > currentState . eFlags & EF_ALT_FIRING ) & & cent - > currentState . weapon = = WP_DISRUPTOR )
)
{ /*continue*/ }
else
return ;
}
// Find the impact point of the beam
if ( cent - > currentState . clientNum = = cg . snap - > ps . clientNum
& & ! cg . renderingThirdPerson ) {
// take origin from view
/*
VectorCopy ( cg . refdef . vieworg , origin ) ;
VectorMA ( origin , - 8 , cg . refdef . viewaxis [ 2 ] , origin ) ;
VectorMA ( origin , 8 , cg . refdef . viewaxis [ 0 ] , origin ) ;
VectorMA ( origin , - 2 , cg . refdef . viewaxis [ 1 ] , origin ) ;
*/
VectorCopy ( cg . refdef . viewaxis [ 0 ] , forward ) ;
VectorCopy ( cg . refdef . vieworg , startpos ) ;
}
else
{
// take origin from entity
if ( cent - > currentState . clientNum = = cg . snap - > ps . clientNum )
AngleVectors ( cg . predictedPlayerState . viewangles , forward , NULL , NULL ) ;
else
AngleVectors ( cent - > lerpAngles , forward , NULL , NULL ) ;
VectorCopy ( origin , startpos ) ;
// Check first from the center to the muzzle.
CG_Trace ( & trace , cent - > lerpOrigin , vec3_origin , vec3_origin , origin , cent - > currentState . number , MASK_SHOT ) ;
if ( trace . fraction < 1.0 )
{ // We hit something here... Stomp the muzzle back to the eye...
VectorCopy ( cent - > lerpOrigin , startpos ) ;
if ( cg . snap - > ps . eFlags & EF_FULL_ROTATE & & Q_fabs ( cg . snap - > ps . viewangles [ PITCH ] ) > 89.0f )
startpos [ 2 ] - = 20 ;
else
startpos [ 2 ] + = cg . snap - > ps . viewheight ;
}
}
VectorMA ( startpos , RANGE_BEAM , forward , endpos ) ;
// Add a subtle variation to the beam weapon's endpoint
/*for (i = 0; i < 3; i ++ )
{
endpos [ i ] + = crandom ( ) * BEAM_VARIATION ;
} */
CG_Trace ( & trace , startpos , vec3_origin , vec3_origin , endpos , cent - > currentState . number , MASK_SHOT ) ;
// traceEnt = &g_entities[ trace.entityNum ];
// Make sparking be a bit less frame-rate dependent..also never add sparking when we hit a surface with a NOIMPACT flag
if ( ! ( trace . surfaceFlags & SURF_NOIMPACT ) )
{
spark = qtrue ;
}
// Don't draw certain kinds of impacts when it hits a player and such..or when we hit a surface with a NOIMPACT flag
if ( cg_entities [ trace . entityNum ] . currentState . eType = = ET_PLAYER | | ( trace . surfaceFlags & SURF_NOIMPACT ) )
{
impact = qfalse ;
}
// Add in the effect
switch ( cent - > currentState . weapon )
{
case WP_PHASER :
if ( cg . snap - > ps . rechargeTime = = 0 )
{
if ( cent - > currentState . eFlags & EF_ALT_FIRING )
FX_PhaserAltFire ( origin , trace . endpos , trace . plane . normal , spark , impact , cent - > pe . empty ) ;
else
FX_PhaserFire ( origin , trace . endpos , trace . plane . normal , spark , impact , cent - > pe . empty ) ;
}
break ;
case WP_COMPRESSION_RIFLE :
if ( cent - > currentState . eFlags & EF_ALT_FIRING )
{
FX_PrifleBeamFire ( origin , trace . endpos , trace . plane . normal , spark , impact , cent - > pe . empty ) ;
}
break ;
case WP_HYPERSPANNER :
if ( cent - > currentState . eFlags & EF_ALT_FIRING )
FX_ProbeBeam ( origin , forward , cent - > currentState . clientNum , qtrue ) ;
else
FX_ProbeBeam ( origin , forward , cent - > currentState . clientNum , qfalse ) ;
break ;
case WP_DERMAL_REGEN :
if ( cent - > currentState . eFlags & EF_ALT_FIRING )
FX_RegenBeam ( origin , forward , cent - > currentState . clientNum , qtrue ) ;
else
FX_RegenBeam ( origin , forward , cent - > currentState . clientNum , qfalse ) ;
break ;
case WP_DISRUPTOR :
if ( cent - > currentState . eFlags & EF_FIRING & & ! ( cent - > currentState . eFlags & EF_ALT_FIRING ) )
FX_DisruptorBeamFire ( origin , trace . endpos , trace . plane . normal , spark , impact , cent - > pe . empty ) ;
/* case WP_DERMAL_REGEN:
if ( ! ( cent - > currentState . eFlags & EF_ALT_FIRING ) )
{
vec3_t org ;
// Move the beam back a bit to help cover up the poly edges on the fire beam
VectorMA ( origin , - 4 , forward , org ) ;
FX_DreadnoughtFire ( org , trace . endpos , trace . plane . normal , spark , impact ) ;
}
break ; */
}
}
/*
= = = = = = = = = = = = = = = = = = = = = =
CG_MachinegunSpinAngle
= = = = = = = = = = = = = = = = = = = = = =
*/
# define SPIN_SPEED 0.9
# define COAST_TIME 1000
static float CG_MachinegunSpinAngle ( centity_t * cent ) {
int delta ;
float angle ;
float speed ;
delta = cg . time - cent - > pe . barrelTime ;
if ( cent - > pe . barrelSpinning ) {
angle = cent - > pe . barrelAngle + delta * SPIN_SPEED ;
} else {
if ( delta > COAST_TIME ) {
delta = COAST_TIME ;
}
speed = 0.5 * ( SPIN_SPEED + ( float ) ( COAST_TIME - delta ) / COAST_TIME ) ;
angle = cent - > pe . barrelAngle + delta * speed ;
}
if ( cent - > pe . barrelSpinning = = ! ( cent - > currentState . eFlags & EF_FIRING ) ) {
cent - > pe . barrelTime = cg . time ;
cent - > pe . barrelAngle = AngleMod ( angle ) ;
cent - > pe . barrelSpinning = ! ! ( cent - > currentState . eFlags & EF_FIRING ) ;
}
return angle ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
CG_AddWeaponWithPowerups
= = = = = = = = = = = = = = = = = = = = = = = =
*/
static void CG_AddWeaponWithPowerups ( refEntity_t * gun , int powerups , beamData_t * beamData , int cloakTime , int decloakTime ) //
{
// add powerup effects
if ( powerups & ( 1 < < PW_INVIS ) | | ( ! ( powerups & ( 1 < < PW_INVIS ) ) & & decloakTime > 0 ) ) {
//TiM - modified so it persists during the first bit of cloaking / last of decloaking
if ( ( cloakTime < = 0 & & decloakTime < = 0 ) | | ( decloakTime > 0 & & cg . time < ( decloakTime + Q_FLASH_TIME * 0.5 ) )
| | ( cloakTime > 0 & & cg . time > ( cloakTime + Q_FLASH_TIME * 0.5 ) ) )
{
if ( /*cg.snap->ps.persistant[PERS_CLASS] == PC_ADMIN*/ cgs . clientinfo [ cg . snap - > ps . clientNum ] . isAdmin )
{ //admins can see cloaked people
//gun->customShader = cgs.media.teleportEffectShader;
//TiM - Make it look cooler - Half invis
gun - > renderfx | = RF_FORCE_ENT_ALPHA ;
gun - > shaderRGBA [ 3 ] = ( unsigned char ) ( 0.4f * 255.0f ) ;
trap_R_AddRefEntityToScene ( gun ) ;
}
}
else
trap_R_AddRefEntityToScene ( gun ) ;
//gun->customShader = cgs.media.invisShader;
//trap_R_AddRefEntityToScene( gun );
}
else if ( powerups & ( 1 < < PW_BEAM_OUT ) | | powerups & ( 1 < < PW_QUAD ) )
{
int btime ;
btime = cg . time - beamData - > beamTimeParam ;
if ( btime < = PLAYER_BEAM_FADE ) {
if ( powerups & ( 1 < < PW_BEAM_OUT ) ) {
gun - > shaderRGBA [ 3 ] = 255 ;
}
else {
gun - > shaderRGBA [ 3 ] = 0 ;
}
}
else if ( btime > = ( PLAYER_BEAM_FADE + PLAYER_BEAM_FADETIME ) ) {
if ( powerups & ( 1 < < PW_BEAM_OUT ) ) {
gun - > shaderRGBA [ 3 ] = 0 ;
}
else {
gun - > shaderRGBA [ 3 ] = 255 ;
}
}
if ( btime > PLAYER_BEAM_FADE & & btime < ( PLAYER_BEAM_FADE + PLAYER_BEAM_FADETIME ) )
{
gun - > renderfx | = RF_FORCE_ENT_ALPHA ;
gun - > shaderRGBA [ 3 ] = ( int ) ( 255 * beamData - > beamAlpha ) ;
}
if ( gun - > shaderRGBA [ 3 ] > 0 ) {
trap_R_AddRefEntityToScene ( gun ) ;
gun - > renderfx & = ~ RF_FORCE_ENT_ALPHA ;
gun - > shaderRGBA [ 3 ] = 255 ;
}
//Just a precaution. Loop it once, then the player should be invisible
if ( btime < 4100 ) {
gun - > customShader = cgs . media . transportShader ;
gun - > shaderTime = beamData - > beamTimeParam * 0.001 ;
trap_R_AddRefEntityToScene ( gun ) ;
}
} else if ( powerups & ( 1 < < PW_BORG_ADAPT ) ) {
gun - > renderfx | = RF_FORCE_ENT_ALPHA ;
gun - > shaderRGBA [ 3 ] = 255 ;
trap_R_AddRefEntityToScene ( gun ) ;
gun - > customShader = cgs . media . borgFullBodyShieldShader ;
trap_R_AddRefEntityToScene ( gun ) ;
return ;
}
else {
trap_R_AddRefEntityToScene ( gun ) ;
if ( gun - > renderfx & RF_FORCE_ENT_ALPHA ) {
gun - > renderfx & = ~ RF_FORCE_ENT_ALPHA ;
}
/* if ( powerups & ( 1 << PW_BOLTON ) ) {
gun - > customShader = cgs . media . battleWeaponShader ;
trap_R_AddRefEntityToScene ( gun ) ;
} */
/* if ( powerups & ( 1 << PW_QUAD ) ) {
gun - > customShader = cgs . media . quadWeaponShader ;
trap_R_AddRefEntityToScene ( gun ) ;
} */
/*if (powerups & (1 << PW_OUCH))
{
gun - > customShader = cgs . media . holoOuchShader ;
// set rgb to 1 of 16 values from 0 to 255. don't use random so that the three
//parts of the player model as well as the gun will all look the same
gun - > shaderRGBA [ 0 ] =
gun - > shaderRGBA [ 1 ] =
gun - > shaderRGBA [ 2 ] = ( ( cg . time % 17 ) * 0.0625 ) * 255 ; //irandom(0,255);
trap_R_AddRefEntityToScene ( gun ) ;
} */
}
}
/*void CG_CoffeeSteamFirstPerson ( refEntity_t* parent, weaponInfo_t *weapon ) {
refEntity_t steam ;
vec3_t angle = { 0.0 , 0.0 , 6.0 } ;
CG_PositionEntityOnTag ( & steam , parent , weapon - > viewModel , " tag_steam1 " ) ;
if ( VectorCompare ( steam . origin , parent - > origin ) ) { //whelp, for some whacky reason, there's no tag O_o
return ;
}
//CG_Steam( steam.origin, angle);
//Disables the OpenGL Hack where the viewmodel is drawn over EVERYTHING ELSE INCLUDING THE STEAM
parent - > renderfx & = ~ RF_DEPTHHACK ;
if ( cg . time % 10 = = 0 ) {
FX_AddSprite ( steam . origin ,
angle , qfalse ,
( random ( ) * 3 + 1 ) , ( 10 ) , //random() * 4 + 2 //12
0.6 + random ( ) * 0.4 , 0.0 ,
random ( ) * 120 , //180
0.0 ,
1300 , //300 //random() * 200 + 1200, //300 //
cgs . media . steamShader ) ;
}
2011-06-09 10:27:51 +00:00
localEntity_t * FX_AddSprite ( vec3_t origin , vec3_t velocity , qboolean gravity , float scale , float dscale ,
2011-06-01 12:20:56 +00:00
float startalpha , float endalpha , float roll , float elasticity ,
float killTime , qhandle_t shader ) */
//if (
/*}
void CG_CoffeeSteamThirdPerson ( refEntity_t * parent , weaponInfo_t * weapon ) {
refEntity_t steam ;
localEntity_t * le = NULL ;
vec3_t angle = { 0.0 , 0.0 , 6.0 } ;
CG_PositionEntityOnTag ( & steam , parent , weapon - > weaponModel , " tag_steam " ) ;
if ( VectorCompare ( steam . origin , parent - > origin ) ) { //whelp, for some whacky reason, there's no tag O_o
return ;
}
if ( cg . time % 10 = = 0 ) {
le = FX_AddSprite ( steam . origin ,
angle , qfalse ,
( random ( ) * 1.2 + 0.5 ) , ( 5 ) , //random() * 4 + 2 //12
0.6 + random ( ) * 0.4 , 0.0 ,
random ( ) * 120 , //180
0.0 ,
1300 , //300 //random() * 200 + 1200, //300 //
cgs . media . steamShader ) ;
}
2011-06-09 10:27:51 +00:00
localEntity_t * FX_AddSprite ( vec3_t origin , vec3_t velocity , qboolean gravity , float scale , float dscale ,
2011-06-01 12:20:56 +00:00
float startalpha , float endalpha , float roll , float elasticity ,
float killTime , qhandle_t shader ) */
//if (
//}*/
void CG_CoffeeSteam ( refEntity_t * parent , weaponInfo_t * weapon , qboolean thirdperson ) {
refEntity_t steam ;
localEntity_t * le ;
vec3_t angle = { 0.0 , 0.0 , 10.0 } ;
//FIXME: I probably should name the tag the same thing in both models... O_o
if ( ! thirdperson ) {
CG_PositionEntityOnTag ( & steam , parent , weapon - > viewModel , " tag_steam1 " ) ;
}
else {
CG_PositionEntityOnTag ( & steam , parent , weapon - > weaponModel , " tag_steam " ) ;
}
if ( VectorCompare ( steam . origin , parent - > origin ) ) { //whelp, for some whacky reason, there's no tag O_o
return ;
}
//CG_Steam( steam.origin, angle);
//Disables the OpenGL Hack where the viewmodel is drawn over EVERYTHING ELSE INCLUDING THE STEAM
parent - > renderfx & = ~ RF_DEPTHHACK ;
if ( cg . time % 10 = = 0 ) { //release a sprite every .01 of a second
le = FX_AddSprite ( steam . origin ,
angle , qfalse ,
( thirdperson ? random ( ) * 1.2 + 0.5 : random ( ) * 1 + 1 ) , ( thirdperson ? 7 : 10 ) , //random() * 4 + 2 //12
0.05 + random ( ) * 0.1 , 0.0 ,
random ( ) * 120 , //180
0.0 ,
1500 , //300 //random() * 200 + 1200, //300 //
cgs . media . steamShader ) ;
}
/*localEntity_t *FX_AddSprite(vec3_t origin, vec3_t velocity, qboolean gravity, float scale, float dscale,
float startalpha , float endalpha , float roll , float elasticity ,
float killTime , qhandle_t shader ) */
//Without this, the steam gets drawn behind the cup... which looks weird
//le->refEntity.renderfx |= RF_DEPTHHACK;
}
/*
= = = = = = = = = = = = =
getClassColor
RPG - X : TiM - used to determine what color skins the weapons should have applied to them
My way of having to not have to enter in so many conditionals over and over
= = = = = = = = = = = = =
*/
//char *getClassColor ( void )
//{
// /*if (( cg.snap->ps.persistant[PERS_CLASS] == PC_SECURITY )
// || ( cg.snap->ps.persistant[PERS_CLASS] == PC_ENGINEER))
// {
// return "default";
// }
//
// if (( cg.snap->ps.persistant[PERS_CLASS] == PC_SCIENCE )
// || ( cg.snap->ps.persistant[PERS_CLASS] == PC_MEDICAL )
// || ( cg.snap->ps.persistant[PERS_CLASS] == PC_ALPHAOMEGA22 ))
// {
// return "teal";
// }
//
// if ((cg.snap->ps.persistant[PERS_CLASS] == PC_COMMAND)
// || (cg.snap->ps.persistant[PERS_CLASS] == PC_ADMIN))
// {
// return "red";
// }
// if ( cg.snap->ps.persistant[PERS_CLASS] == PC_NOCLASS ) {
// return "NULL";
// }*/
//
// //lolz... this time, let's base it off of current model
// //rather than class
// cgs.clientinfo[0].
//
// return "default";
//}
/*
= = = = = = = = = = = = =
CG_AddPlayerWeapon
Used for both the view weapon ( ps is valid ) and the world modelother character models ( ps is NULL )
The main player will have this called for BOTH cases , so effects like light and
sound should only be done on the world model case .
= = = = = = = = = = = = =
*/
void CG_AddPlayerWeapon ( refEntity_t * parent , playerState_t * ps , centity_t * cent ) {
refEntity_t gun ;
refEntity_t barrel ;
refEntity_t flash ;
vec3_t angles ;
weapon_t weaponNum ;
weaponInfo_t * weapon ;
centity_t * nonPredictedCent ;
int i = 0 , numBarrels = 0 ;
wpnBarrelInfo_t * barrelInfo = NULL ;
char filename [ MAX_QPATH ] ;
char * skinColor ;
weaponNum = cent - > currentState . weapon ;
CG_RegisterWeapon ( weaponNum ) ;
weapon = & cg_weapons [ weaponNum ] ;
// add the weapon
memset ( & gun , 0 , sizeof ( gun ) ) ;
VectorCopy ( parent - > lightingOrigin , gun . lightingOrigin ) ;
gun . shadowPlane = parent - > shadowPlane ;
gun . renderfx = parent - > renderfx ;
// set custom shading for railgun refire rate
/*if ( ps ) {
if ( cg . predictedPlayerState . weapon = = WP_NULL_HAND
& & cg . predictedPlayerState . weaponstate = = WEAPON_FIRING ) {
float f ;
f = ( float ) cg . predictedPlayerState . weaponTime / 1500 ;
gun . shaderRGBA [ 1 ] = 0 ;
gun . shaderRGBA [ 0 ] =
gun . shaderRGBA [ 2 ] = 255 * ( 1.0 - f ) ;
} else {
gun . shaderRGBA [ 0 ] = 255 ;
gun . shaderRGBA [ 1 ] = 255 ;
gun . shaderRGBA [ 2 ] = 255 ;
gun . shaderRGBA [ 3 ] = 255 ;
}
} */
if ( ps )
{
qhandle_t skin ;
gun . hModel = weapon - > viewModel ;
skinColor = cgs . clientinfo [ cg . snap - > ps . clientNum ] . skinName ;
//if ( skinColor != "NULL" ) { //RPG-X : TiM - Will change the color of the band on the viewmodel's arm, depending what class
if ( ! Q_stricmpn ( skinColor , " NULL " , 4 ) ) {
for ( i = 0 ; i < 8 ; i + + ) {
if ( cg . predictedPlayerState . weapon = = ( RAweapons [ i ] ) ) {
Com_sprintf ( filename , sizeof ( filename ) , " models/weapons2/%s/model_%s.skin " , RAweapFileName [ i ] , skinColor ) ; //Formulate the skin route
skin = trap_R_RegisterSkin ( filename ) ;
if ( ! skin )
break ;
gun . customSkin = skin ; //and 'plonk' it on the model :)
break ;
}
}
}
}
else
{
gun . hModel = weapon - > weaponModel ;
}
if ( ! gun . hModel ) {
return ;
}
if ( ! ps ) {
// add weapon stop sound
if ( ! ( cent - > currentState . eFlags & EF_FIRING ) & & ! ( cent - > currentState . eFlags & EF_ALT_FIRING ) & & cent - > pe . lightningFiring & &
cg . predictedPlayerState . ammo [ cg . predictedPlayerState . weapon ] )
{
if ( weapon - > stopSound )
{
trap_S_StartSound ( cent - > lerpOrigin , cent - > currentState . number , CHAN_WEAPON , weapon - > stopSound ) ;
}
else if ( weapon - > altStopSound )
{
trap_S_StartSound ( cent - > lerpOrigin , cent - > currentState . number , CHAN_WEAPON , weapon - > altStopSound ) ;
}
}
cent - > pe . lightningFiring = qfalse ;
if ( cent - > currentState . eFlags & EF_ALT_FIRING )
{
// hark, I smell hackery afoot
if ( ( weaponNum = = WP_PHASER ) & & ! ( cg . predictedPlayerState . ammo [ WP_PHASER ] ) )
{
trap_S_AddLoopingSound ( cent - > currentState . number , cent - > lerpOrigin , vec3_origin , cgs . media . phaserEmptySound ) ;
cent - > pe . lightningFiring = qtrue ;
}
else if ( weapon - > altFiringSound & & ! weapon - > isAnimSndBased )
{
trap_S_AddLoopingSound ( cent - > currentState . number , cent - > lerpOrigin , vec3_origin , weapon - > altFiringSound ) ;
cent - > pe . lightningFiring = qtrue ;
}
if ( weaponNum = = WP_TOOLKIT | | weaponNum = = WP_MEDKIT ) {
cent - > pe . lightningFiring = qtrue ;
}
}
else if ( cent - > currentState . eFlags & EF_FIRING )
{
if ( ( weaponNum = = WP_PHASER ) & & ! ( cg . predictedPlayerState . ammo [ WP_PHASER ] ) )
{
trap_S_AddLoopingSound ( cent - > currentState . number , cent - > lerpOrigin , vec3_origin , cgs . media . phaserEmptySound ) ;
cent - > pe . lightningFiring = qtrue ;
}
else if ( weapon - > firingSound & & ! weapon - > isAnimSndBased )
{
trap_S_AddLoopingSound ( cent - > currentState . number , cent - > lerpOrigin , vec3_origin , weapon - > firingSound ) ;
cent - > pe . lightningFiring = qtrue ;
}
//TiM: Haxxor. I want the medkit + toolkit sounds to play only once when u hold them down
if ( weaponNum = = WP_TOOLKIT | | weaponNum = = WP_MEDKIT ) {
cent - > pe . lightningFiring = qtrue ;
}
}
}
CG_PositionEntityOnTag ( & gun , parent , parent - > hModel , " tag_weapon " ) ;
//RPG-X : TiM - A little variety here :) Toolkit gets attached to player model's left hand, medkit on waist :)
//Hack: I dunno why, but unless I specified thirdperson (ie (!ps) ), the viewmodel went crazy. :P
if ( ! ps ) {
if ( ( weaponNum = = WP_TOOLKIT ) ) { //Toolkit //cg.predictedPlayerState.weapon
CG_PositionEntityOnTag ( & gun , parent , parent - > hModel , " tag_lhand " ) ;
}
else if ( ( weaponNum = = WP_MEDKIT ) ) { //Medkit
CG_PositionEntityOnTag ( & gun , parent , parent - > hModel , " tag_torso " ) ;
}
/*else {
CG_PositionEntityOnTag ( & gun , parent , parent - > hModel , " tag_weapon " ) ;
} */
//TiM: also in the hopes of keeping the weapon scale constant in contrast to the player model
gun . nonNormalizedAxes = qfalse ;
}
if ( weaponNum = = WP_COFFEE ) {
if ( ! ps ) {
if ( ! ( ! cg . renderingThirdPerson & & cent - > currentState . clientNum = = cg . predictedPlayerState . clientNum ) )
CG_CoffeeSteam ( & gun , weapon , qtrue ) ;
}
//else {
// CG_CoffeeSteam( &gun, weapon, qfalse );
//}
}
CG_AddWeaponWithPowerups ( & gun , cent - > currentState . powerups , & cent - > beamData , cent - > cloakTime , cent - > decloakTime ) ;
// add the spinning barrel
//
//
for ( barrelInfo = wpnBarrelData ; barrelInfo - > giTag ! = WP_NONE ; barrelInfo + + )
{
if ( barrelInfo - > giTag = = weaponNum )
{
numBarrels = barrelInfo - > numBarrels ;
break ;
}
}
// don't add barrels to world model...only viewmodels
if ( ps )
{
for ( i = 0 ; i < numBarrels ; i + + )
{
memset ( & barrel , 0 , sizeof ( barrel ) ) ;
VectorCopy ( parent - > lightingOrigin , barrel . lightingOrigin ) ;
barrel . shadowPlane = parent - > shadowPlane ;
barrel . renderfx = parent - > renderfx ;
barrel . hModel = weapon - > barrelModel [ i ] ;
angles [ YAW ] = 0 ;
angles [ PITCH ] = 0 ;
if ( weaponNum = = WP_TR116 ) {
angles [ ROLL ] = CG_MachinegunSpinAngle ( cent ) ;
} else {
angles [ ROLL ] = 0 ; //CG_MachinegunSpinAngle( cent );
}
AnglesToAxis ( angles , barrel . axis ) ;
if ( ! i ) {
CG_PositionRotatedEntityOnTag ( & barrel , parent , weapon - > handsModel , " tag_barrel " ) ;
} else {
CG_PositionRotatedEntityOnTag ( & barrel , parent , weapon - > handsModel , va ( " tag_barrel%d " , i + 1 ) ) ;
}
CG_AddWeaponWithPowerups ( & barrel , cent - > currentState . powerups , & cent - > beamData , cent - > cloakTime , cent - > decloakTime ) ;
}
}
// make sure we aren't looking at cg.predictedPlayerEntity for LG
nonPredictedCent = & cg_entities [ cent - > currentState . clientNum ] ;
// if the index of the nonPredictedCent is not the same as the clientNum
// then this is a fake player (like on teh single player podiums), so
// go ahead and use the cent
if ( ( nonPredictedCent - cg_entities ) ! = cent - > currentState . clientNum ) {
nonPredictedCent = cent ;
}
//Com_Printf("eType: %i, eventParm: %i, weaponNum: %i\n", cent->currentState.eType, cent->currentState.eventParm, weaponNum);
if ( weaponNum = = WP_COMPRESSION_RIFLE
& &
cent - > currentState . powerups & ( 1 < < PW_FLASHLIGHT )
& &
cent - > beamData . beamTimeParam = = 0
& &
( ! ( cent - > currentState . powerups & ( 1 < < PW_INVIS ) )
| | cent - > currentState . clientNum = = cg . predictedPlayerState . clientNum )
)
{ //FIXME: TiM - need to know if flashlight is on or off at the time :S
refEntity_t flashlight ;
memset ( & flashlight , 0 , sizeof ( flashlight ) ) ;
VectorCopy ( parent - > lightingOrigin , flashlight . lightingOrigin ) ;
flashlight . shadowPlane = parent - > shadowPlane ;
flashlight . renderfx = parent - > renderfx ;
flashlight . hModel = cgs . media . flashlightModel ;
if ( ! flashlight . hModel ) {
return ;
}
angles [ YAW ] = 0 ;
angles [ PITCH ] = 0 ;
angles [ ROLL ] = 0 ;
AnglesToAxis ( angles , flashlight . axis ) ;
if ( ps )
{ // Rendering inside the head...
CG_PositionRotatedEntityOnTag ( & flashlight , & gun , weapon - > viewModel , " tag_flashlight " ) ;
}
else
{ // Rendering outside the head...
CG_PositionRotatedEntityOnTag ( & flashlight , & gun , weapon - > weaponModel , " tag_flashlight " ) ;
}
trap_R_AddRefEntityToScene ( & flashlight ) ;
}
// add the flash
if ( ( weaponNum = = WP_PHASER | |
weaponNum = = WP_DERMAL_REGEN )
& & ( nonPredictedCent - > currentState . eFlags & EF_FIRING ) )
{
// continuous flash
}
else
{
// impulse flash
//if ( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME) {
if ( cg . time - cent - > muzzleFlashTime > wpnBarrelData [ weaponNum - 1 ] . flashTime )
{
return ;
}
}
memset ( & flash , 0 , sizeof ( flash ) ) ;
VectorCopy ( parent - > lightingOrigin , flash . lightingOrigin ) ;
flash . shadowPlane = parent - > shadowPlane ;
flash . renderfx = parent - > renderfx ;
flash . hModel = weapon - > flashModel ;
if ( ! flash . hModel ) {
return ;
}
angles [ YAW ] = 0 ;
angles [ PITCH ] = 0 ;
angles [ ROLL ] = 0 ; //angles[ROLL] = crandom() * 10; //RPG-X - TiM: This stops the lensflare on the muzzle from jiggling around
AnglesToAxis ( angles , flash . axis ) ;
//TiM - Instead of briefly showing the flash, show it scaling down
if ( weaponNum ! = WP_PHASER & &
weaponNum ! = WP_HYPERSPANNER & &
weaponNum ! = WP_DERMAL_REGEN & &
! ( weaponNum = = WP_COMPRESSION_RIFLE & & ( cent - > currentState . eFlags & EF_ALT_FIRING ) ) & &
! ( weaponNum = = WP_DISRUPTOR & & ! ( cent - > currentState . eFlags & EF_ALT_FIRING ) )
)
{
float scale ;
scale = ( 1.0f - ( ( float ) ( cg . time - cent - > muzzleFlashTime ) / ( float ) wpnBarrelData [ weaponNum - 1 ] . flashTime ) ) * 2.0f ;
flash . nonNormalizedAxes = qtrue ;
VectorScale ( flash . axis [ 0 ] , scale , flash . axis [ 0 ] ) ;
VectorScale ( flash . axis [ 1 ] , scale , flash . axis [ 1 ] ) ;
VectorScale ( flash . axis [ 2 ] , scale , flash . axis [ 2 ] ) ;
}
//TiM - quick hack
//jiggle the scale of the phaser rifle on alt fire around
if ( ( weaponNum = = WP_COMPRESSION_RIFLE & & ( cent - > currentState . eFlags & EF_ALT_FIRING ) )
| |
( weaponNum = = WP_DISRUPTOR & & ! ( cent - > currentState . eFlags & EF_ALT_FIRING ) ) )
{
float min , max ;
if ( weaponNum = = WP_COMPRESSION_RIFLE )
{
min = 1.3f ;
max = 1.6f ;
}
else
{
min = 0.8f ;
max = 0.9f ;
}
VectorScale ( flash . axis [ 0 ] , flrandom ( min , max ) , flash . axis [ 0 ] ) ;
VectorScale ( flash . axis [ 1 ] , flrandom ( min , max ) , flash . axis [ 1 ] ) ;
VectorScale ( flash . axis [ 2 ] , flrandom ( min , max ) , flash . axis [ 2 ] ) ;
}
if ( cent - > pe . empty )
{ // Make muzzle flash wussy when empty.
flash . customShader = cgs . media . phaserMuzzleEmptyShader ;
}
if ( ps )
{ // Rendering inside the head...
CG_PositionRotatedEntityOnTag ( & flash , & gun , weapon - > viewModel , " tag_flash " ) ;
}
else
{ // Rendering outside the head...
CG_PositionRotatedEntityOnTag ( & flash , & gun , weapon - > weaponModel , " tag_flash " ) ;
}
if ( ! ( cent - > currentState . powerups & ( 1 < < PW_INVIS ) )
| | cent - > currentState . clientNum = = cg . predictedPlayerState . clientNum )
{
trap_R_AddRefEntityToScene ( & flash ) ;
}
if ( ps | | cg . renderingThirdPerson | | cent - > currentState . number ! = cg . predictedPlayerState . clientNum | | cg_firstPersonBody . integer )
{
// add phaser/dreadnought
// grrr nonPredictedCent doesn't have the proper empty setting
nonPredictedCent - > pe . empty = cent - > pe . empty ;
CG_LightningBolt ( nonPredictedCent , flash . origin ) ;
// make a dlight for the flash
if ( ( weapon - > flashDlightColor [ 0 ] | | weapon - > flashDlightColor [ 1 ] | | weapon - > flashDlightColor [ 2 ] ) & & ! ( cent - > currentState . powerups & ( 1 < < PW_INVIS ) ) ) {
trap_R_AddLightToScene ( flash . origin , 200 + ( rand ( ) & 31 ) , weapon - > flashDlightColor [ 0 ] ,
weapon - > flashDlightColor [ 1 ] , weapon - > flashDlightColor [ 2 ] ) ;
}
}
}
/*
= = = = = = = = = = = = = =
CG_AddViewWeapon
Add the weapon , and flash for the player ' s view
= = = = = = = = = = = = = =
*/
void CG_AddViewWeapon ( playerState_t * ps ) {
refEntity_t hand ;
centity_t * cent ;
clientInfo_t * ci ;
float fovOffset ;
vec3_t angles ;
weaponInfo_t * weapon ;
if ( ps - > persistant [ PERS_TEAM ] = = TEAM_SPECTATOR /*|| (ps->eFlags&EF_ELIMINATED)*/ ) {
return ;
}
if ( ps - > pm_type = = PM_INTERMISSION ) {
return ;
}
// no gun if in third person view
if ( cg . renderingThirdPerson | | cg_firstPersonBody . integer ) {
return ;
}
// allow the gun to be completely removed
//TiM: Added alt fire for alt-fire beam weapons
if ( ! cg_drawGun . integer | | cg . zoomed ) {
vec3_t origin ;
if ( cg . predictedPlayerState . eFlags & EF_FIRING | | cg . predictedPlayerState . eFlags & EF_ALT_FIRING )
{
// special hack for phaser/dreadnought...
VectorCopy ( cg . refdef . vieworg , origin ) ;
VectorMA ( origin , - 8 , cg . refdef . viewaxis [ 2 ] , origin ) ;
CG_LightningBolt ( & cg_entities [ ps - > clientNum ] , origin ) ;
}
return ;
}
if ( ( cg . zoomed ) & & ( ps - > weapon = = WP_COMPRESSION_RIFLE ) ) { //RPG-X : TiM - People were saying that being able to see the gunsight on the rifle thru the gunsight in zoom mode was weird :P
return ;
}
// don't draw if testing a gun model
if ( cg . testGun ) {
return ;
}
// drop gun lower at higher fov
if ( cg_fov . integer > 80 ) {
fovOffset = - 0.2 * ( cg_fov . integer - 80 ) ;
} else {
fovOffset = 0 ;
}
cent = & cg . predictedPlayerEntity ; // &cg_entities[cg.snap->ps.clientNum];
CG_RegisterWeapon ( ps - > weapon ) ;
weapon = & cg_weapons [ ps - > weapon ] ;
memset ( & hand , 0 , sizeof ( hand ) ) ;
// set up gun position
CG_CalculateWeaponPosition ( hand . origin , angles ) ;
VectorMA ( hand . origin , cg_gun_x . value , cg . refdef . viewaxis [ 0 ] , hand . origin ) ;
VectorMA ( hand . origin , cg_gun_y . value , cg . refdef . viewaxis [ 1 ] , hand . origin ) ;
VectorMA ( hand . origin , ( cg_gun_z . value + fovOffset ) , cg . refdef . viewaxis [ 2 ] , hand . origin ) ;
AnglesToAxis ( angles , hand . axis ) ;
// map torso animations to weapon animations
if ( cg_gun_frame . integer ) {
// development tool
hand . frame = hand . oldframe = cg_gun_frame . integer ;
hand . backlerp = 0 ;
} else {
// get clientinfo for animation map
ci = & cgs . clientinfo [ cent - > currentState . clientNum ] ;
hand . frame = CG_MapTorsoToWeaponFrame ( ci , cent - > pe . torso . frame ) ;
hand . oldframe = CG_MapTorsoToWeaponFrame ( ci , cent - > pe . torso . oldFrame ) ;
hand . backlerp = cent - > pe . torso . backlerp ;
}
hand . hModel = weapon - > handsModel ;
hand . renderfx = RF_DEPTHHACK | RF_FIRST_PERSON ;
// add everything onto the hand
CG_AddPlayerWeapon ( & hand , ps , & cg . predictedPlayerEntity ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
WEAPON SELECTION
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void static CG_RegisterWeaponIcon ( int weaponNum ) {
weaponInfo_t * weaponInfo ;
gitem_t * item ;
weaponInfo = & cg_weapons [ weaponNum ] ;
if ( weaponNum = = 0 ) {
return ;
}
if ( weaponInfo - > registered ) {
return ;
}
for ( item = bg_itemlist + 1 ; item - > classname ; item + + ) {
if ( item - > giType = = IT_WEAPON & & item - > giTag = = weaponNum ) {
weaponInfo - > item = item ;
break ;
}
}
if ( ! item - > classname ) {
CG_Error ( " Couldn't find weapon %i " , weaponNum ) ;
}
weaponInfo - > weaponIcon = trap_R_RegisterShader ( item - > icon ) ;
}
/*
= = = = = = = = = = = = = = = = = =
CG_DrawWeaponIcon
RPG - X | Phenix | 08 / 06 / 2005
RPG - X | TiM | 5 / 1 / 2006
= = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void CG_DrawWeaponIcon ( int x , int y , int weapon )
{
/*vec4_t color;
color [ 3 ] = alpha ;
if ( ! color [ 3 ] ) {
return ;
} */
CG_RegisterWeaponIcon ( weapon ) ; //short version
// draw selection marker
if ( weapon = = cg . weaponSelect )
{
trap_R_SetColor ( colorTable [ CT_LTPURPLE1 ] ) ;
}
else
{
trap_R_SetColor ( colorTable [ CT_DKPURPLE1 ] ) ;
}
CG_DrawPic ( x - 4 , y - 4 , 38 , 38 , cgs . media . weaponbox ) ;
// draw weapon icon
trap_R_SetColor ( colorTable [ CT_WHITE ] ) ;
CG_DrawPic ( x , y , 32 , 32 , cg_weapons [ weapon ] . weaponIcon ) ;
// draw selection marker
/*if ( weapon == cg.weaponSelect ) {
CG_DrawPic ( x - 4 , y - 4 , 40 , 40 , cgs . media . selectShader ) ; */
//}
trap_R_SetColor ( NULL ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
CG_DrawWeaponSelect
= = = = = = = = = = = = = = = = = = =
*/
2011-06-09 10:27:51 +00:00
static int weaponRows [ 6 ] [ 3 ] = { { WP_NULL_HAND , 0 , 0 } ,
{ WP_TRICORDER , WP_PADD , WP_COFFEE } ,
{ WP_PHASER , WP_COMPRESSION_RIFLE , WP_TR116 } ,
{ WP_GRENADE_LAUNCHER , WP_QUANTUM_BURST , WP_DISRUPTOR } ,
{ WP_MEDKIT , WP_VOYAGER_HYPO , WP_DERMAL_REGEN } ,
{ WP_TOOLKIT , WP_HYPERSPANNER , 0 } } ;
2011-06-01 12:20:56 +00:00
void CG_DrawWeaponSelect ( void ) {
int i , rowCount , cellCount ;
int bits ;
//int count;
int x , y , w , defaultX , defaultY ;
char * name ;
float * color ;
qboolean WeapOnThisRow = qfalse ;
//vec4_t color;
// don't display if dead
if ( cg . predictedPlayerState . stats [ STAT_HEALTH ] < = 1 | | cg . predictedPlayerState . eFlags & EF_DEAD ) { //RPG-X: RedTechie - No weapons at health 1 (you die at health 1 now)
return ;
}
color = CG_FadeColor ( cg . weaponSelectTime , WEAPON_SELECT_TIME ) ;
if ( ! color ) {
return ;
}
// showing weapon select clears pickup item display, but not the blend blob
cg . itemPickupTime = 0 ;
// count the number of weapons owned
bits = cg . snap - > ps . stats [ STAT_WEAPONS ] ;
//NEW HUD FOR RPG-X
defaultX = 18 ;
defaultY = 52 ;
x = defaultX ;
y = ( BIGCHAR_HEIGHT * 2 ) + 20 ;
for ( i = 0 , rowCount = 0 , cellCount = 0 ; i < MAX_WEAPONS ; i + + , cellCount + + ) {
if ( cellCount = = 3 ) { //we've hit the end of the row
rowCount + + ; //go to the next row
cellCount = 0 ; //reset cell clock
if ( WeapOnThisRow ) {
//**** Draw the end caps *****
//VectorCopy( colorTable[CT_LTPURPLE2], color );
trap_R_SetColor ( colorTable [ CT_LTPURPLE2 ] ) ;
// Left end cap
CG_DrawPic ( 2 , y - 5 , 16 , 50 , cgs . media . weaponcap1 ) ; //6
// Right End Cap
CG_DrawPic ( x - 20 + 16 , y - 5 , 16 , 50 , cgs . media . weaponcap2 ) ; //2 - 6, 16 - 18
trap_R_SetColor ( NULL ) ;
y + = defaultY ;
x = defaultX ;
WeapOnThisRow = qfalse ;
}
if ( rowCount > = 6 ) { //if we exceed our rows, that's bad O_o
break ;
}
}
if ( weaponRows [ rowCount ] [ cellCount ] = = 0 ) {
i - - ;
continue ;
}
if ( bits & ( 1 < < weaponRows [ rowCount ] [ cellCount ] ) ) {
CG_DrawWeaponIcon ( x , y , weaponRows [ rowCount ] [ cellCount ] ) ;
x + = 40 ;
if ( ! WeapOnThisRow ) {
WeapOnThisRow = qtrue ;
}
}
}
// END HUD
// draw the selected names
if ( cg_weapons [ cg . weaponSelect ] . item ) {
name = cg_weapons [ cg . weaponSelect ] . item - > pickup_name ;
if ( name ) {
w = UI_ProportionalStringWidth ( name , UI_SMALLFONT ) ;
UI_DrawProportionalString ( x , y , name , UI_SMALLFONT , color ) ;
}
}
trap_R_SetColor ( NULL ) ;
}
/*
= = = = = = = = = = = = = = =
CG_WeaponSelectable
= = = = = = = = = = = = = = =
*/
static qboolean CG_WeaponSelectable ( int i ) {
if ( ! cg . snap - > ps . ammo [ i ] ) {
return qfalse ;
}
if ( ! ( cg . snap - > ps . stats [ STAT_WEAPONS ] & ( 1 < < i ) ) ) {
return qfalse ;
}
return qtrue ;
}
extern int altAmmoUsage [ ] ;
/*
{
0 , //WP_NONE,
2 , //WP_PHASER,
10 , //WP_COMPRESSION_RIFLE,
3 , //WP_NULL_HAND,
5 , //WP_COFFEE,
1 , //WP_DISRUPTOR,
1 , //WP_GRENADE_LAUNCHER,
2 , //WP_TR116,
2 , //WP_QUANTUM_BURST,
5 //WP_DERMAL_REGEN,
20 , //WP_VOYAGER_HYPO,
# #, //WP_TOOLKIT,
# #, //WP_MEDKIT,
} ;
*/
/*
= = = = = = = = = = = = = = =
CG_WeaponAltSelectable
= = = = = = = = = = = = = = =
*/
static qboolean CG_WeaponAltSelectable ( int i ) {
if ( cg . snap - > ps . ammo [ i ] < altAmmoUsage [ cg . snap - > ps . weapon ] ) {
return qfalse ;
}
if ( ! ( cg . snap - > ps . stats [ STAT_WEAPONS ] & ( 1 < < i ) ) ) {
return qfalse ;
}
return qtrue ;
}
/*
= = = = = = = = = = = = = = =
CG_NextWeapon_f
= = = = = = = = = = = = = = =
*/
void CG_NextWeapon_f ( void ) {
int i ; //, topWeapon
int original ;
// int newWeapons[16];
// int bits;
if ( ! cg . snap ) {
return ;
}
if ( cg . snap - > ps . pm_flags & PMF_FOLLOW ) {
return ;
}
cg . weaponSelectTime = cg . time ;
original = cg . weaponSelect ;
//RPG-X | Phenix | 08/06/2005
//Removed to be replaced to scroll through our list
//TiM | 4/1/2006
//Put back in since I optimized the way weapons are handled
for ( i = 0 ; i < 16 ; i + + ) {
cg . weaponSelect + + ;
if ( cg . weaponSelect = = 16 ) {
cg . weaponSelect = 0 ;
}
if ( CG_WeaponSelectable ( cg . weaponSelect ) ) {
break ;
}
}
if ( i = = 16 ) {
cg . weaponSelect = original ;
}
//TiM: Just for the record. Phenix. Enumerated value lists. Look them up. Use them!
//Reading this code was really tricky when it didn't have to be >.<
//ie 1 = WP_PHASER etc
}
/*
= = = = = = = = = = = = = = =
CG_PrevWeapon_f
= = = = = = = = = = = = = = =
*/
void CG_PrevWeapon_f ( void ) {
int i ; //, topWeapon
int original ;
// int newWeapons[16];
// int bits;
if ( ! cg . snap ) {
return ;
}
if ( cg . snap - > ps . pm_flags & PMF_FOLLOW ) {
return ;
}
cg . weaponSelectTime = cg . time ;
original = cg . weaponSelect ;
//RPG-X | Phenix | 08/06/2005
//Removed to be replaced to scroll through our list
//TiM | 4/1/2006
//Put back in since I optimized the way weapons are handled
for ( i = 0 ; i < 16 ; i + + ) {
cg . weaponSelect - - ;
if ( cg . weaponSelect = = - 1 ) {
cg . weaponSelect = 15 ;
}
if ( CG_WeaponSelectable ( cg . weaponSelect ) ) {
break ;
}
}
if ( i = = 16 ) {
cg . weaponSelect = original ;
}
}
/*
= = = = = = = = = = = = = = =
CG_Weapon_f
= = = = = = = = = = = = = = =
*/
/*TiM : Here for reference
static int weaponRows [ 6 ] [ 3 ] = { WP_NULL_HAND , 0 , 0 ,
WP_TRICORDER , WP_PADD , WP_COFFEE ,
WP_PHASER , WP_COMPRESSION_RIFLE , WP_TR116 ,
WP_GRENADE_LAUNCHER , WP_QUANTUM_BURST , WP_DISRUPTOR ,
WP_MEDKIT , WP_VOYAGER_HYPO , WP_DERMAL_REGEN ,
WP_TOOLKIT , WP_NEUTRINO_PROBE , 0 } ; */
void CG_Weapon_f ( void ) {
int num ;
//int newWeapons[16];
int i ;
int bits ;
int weaponsOnRow ;
int weaponGot [ 6 ] ;
int onRow ;
int onCol ;
int rowsUsed ;
int currentWeaponCol ;
if ( ! cg . snap ) {
return ;
}
if ( cg . snap - > ps . pm_flags & PMF_FOLLOW ) {
return ;
}
num = atoi ( CG_Argv ( 1 ) ) ;
bits = cg . snap - > ps . stats [ STAT_WEAPONS ] ;
//TiM - 0 = Null hand weapon now
//if ( num < 1 || num > 15 ) {
if ( num < 0 | | num > 15 ) {
return ;
}
cg . weaponSelectTime = cg . time ;
//Hacky Override: 0 = Null hand no matter what.
if ( num = = 0 ) {
if ( bits & ( 1 < < WP_NULL_HAND ) ) {
cg . weaponSelect = WP_NULL_HAND ;
}
return ;
}
//TiM : The code below went into an infinite loop if a high number was
//set as an arg to this command.
//Lemme just insert a check to make sure the code NEVER accepts args higher
//than the size of our weapons array. I'll put it underneath the weaponSelectTime
//statement, so the user will still see a response to their input.
else if ( num > 5 ) {
return ;
}
/* RPG-X | Phenix | 02/02/2006
*
* Code to group weapons together by keyboard */
//Init weaponGot values
/*for (i = 0; i < 6; i++)
weaponGot [ i ] = - 1 ; */
memset ( weaponGot , - 1 , sizeof ( weaponGot ) ) ;
onCol = 0 ;
weaponsOnRow = 0 ;
rowsUsed = 0 ;
currentWeaponCol = - 1 ;
//Loop though every weapon in weaponRows (starting on row 2 - WHY TIM WHY!)
//TiM: ... because :)
for ( i = 0 , onRow = 1 ; i < 15 ; i + + )
{
if ( onCol = = 3 )
{
onCol = 0 ;
weaponsOnRow = 0 ;
onRow + + ;
if ( onRow > 5 ) //Something has gone wrong!
break ;
}
if ( weaponRows [ onRow ] [ onCol ] > 0 )
{ //Double check this is a weapon
if ( ( bits & ( 1 < < weaponRows [ onRow ] [ onCol ] ) ) & & ( weaponsOnRow = = 0 ) )
{ //If we have this weapon And it is the first weapon on this row we have
weaponGot [ rowsUsed ] = onRow ;
weaponsOnRow + + ;
rowsUsed + + ;
}
if ( ( cg . predictedPlayerState . weapon = = weaponRows [ onRow ] [ onCol ] ) & & ( rowsUsed = = num ) )
{ //If this is the selected weapon record what column it is on
currentWeaponCol = onCol ;
}
}
onCol + + ;
}
//If they selected a row that doesn't exist
if ( weaponGot [ num - 1 ] = = - 1 )
return ; //(dont need to worry about num being zero because of tims hack ^^)
do
{ //Loop though this row until we come accross a weapon which the player has got and is not "null" (0)
currentWeaponCol + + ;
if ( currentWeaponCol = = 3 )
{
currentWeaponCol = 0 ;
}
} while ( ( weaponRows [ weaponGot [ num - 1 ] ] [ currentWeaponCol ] = = 0 ) | | ! ( bits & ( 1 < < weaponRows [ weaponGot [ num - 1 ] ] [ currentWeaponCol ] ) ) ) ;
cg . weaponSelect = weaponRows [ weaponGot [ num - 1 ] ] [ currentWeaponCol ] ;
//TiM - based on the number we pressed, and whichever
//weapons we have in sequential order, select the one that corresponds.
//Start at number 2, skipping null hand. He owns us all
/*for ( i = WP_TRICORDER, weaponCount = 0; i < MAX_WEAPONS; i++ ) {
//if we have that weapon
if ( bits & ( 1 < < i ) ) {
weaponCount + + ;
if ( weaponCount = = num ) {
cg . weaponSelect = i ;
return ;
}
}
} */
}
/*
= = = = = = = = = = = = = = = = = = =
CG_OutOfAmmoChange
The current weapon has just run out of ammo
= = = = = = = = = = = = = = = = = = =
*/
void CG_OutOfAmmoChange ( qboolean altfire ) {
int i ;
cg . weaponSelectTime = cg . time ;
for ( i = 15 ; i > 0 ; i - - )
{
if ( altfire )
{
if ( CG_WeaponAltSelectable ( i ) )
{
cg . weaponSelect = i ;
break ;
}
}
else
{
if ( CG_WeaponSelectable ( i ) )
{
cg . weaponSelect = i ;
break ;
}
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
WEAPON EVENTS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = =
CG_FireWeapon
Caused by an EV_FIRE_WEAPON event
= = = = = = = = = = = = = = = =
*/
int tris_state = 0 ;
void CG_FireWeapon ( centity_t * cent , qboolean alt_fire ) {
entityState_t * ent ;
weaponInfo_t * weap ;
int rpg_effectsgun ;
int rpg_tripmines ;
const char * info ;
//const char *info2;
ent = & cent - > currentState ;
if ( ent - > weapon = = WP_NONE | | ent - > weapon = = WP_NULL_HAND ) {
return ;
}
if ( ent - > weapon > = WP_NUM_WEAPONS ) {
CG_Error ( " CG_FireWeapon: ent->weapon >= WP_NUM_WEAPONS " ) ;
return ;
}
weap = & cg_weapons [ ent - > weapon ] ;
// mark the entity as muzzle flashing, so when it is added it will
// append the flash to the weapon model
cent - > muzzleFlashTime = cg . time ;
// lightning gun only does this this on initial press
if ( ent - > weapon = = WP_PHASER /*||
ent - > weapon = = WP_DERMAL_REGEN */
| | ent - > weapon = = WP_TOOLKIT
| | ent - > weapon = = WP_MEDKIT
| | ( ! ( cent - > currentState . eFlags & EF_ALT_FIRING ) & & ent - > weapon = = WP_DISRUPTOR )
| | ( cent - > currentState . eFlags & EF_ALT_FIRING & & ent - > weapon = = WP_COMPRESSION_RIFLE )
)
{
if ( cent - > pe . lightningFiring ) {
return ;
}
}
// play quad sound if needed
/* if ( cent->currentState.powerups & ( 1 << PW_QUAD ) ) {
trap_S_StartSound ( NULL , cent - > currentState . number , CHAN_ITEM , cgs . media . quadSound ) ;
} */
// play a sound
info = CG_ConfigString ( CS_SERVERINFO ) ;
rpg_tripmines = atoi ( Info_ValueForKey ( info , " rpg_invisibletripmines " ) ) ;
rpg_effectsgun = atoi ( Info_ValueForKey ( info , " rpg_effectsgun " ) ) ;
if ( alt_fire )
{
//RPG-X: RedTechie - Wrong place for show tris
/*if( ent->weapon == WP_TR116 )
{
if ( tris_state = = 1 )
tris_state = 0 ;
else
tris_state = 1 ;
trap_Cvar_Set ( " r_showtris " , va ( " %i " , tris_state ) ) ;
} */
if ( weap - > altFlashSnd )
{
//TiM : Hark, I smell hackery again
//admin alt hypos no fire coz it grinds my teeth
if ( cgs . clientinfo [ cg . snap - > ps . clientNum ] . isAdmin /*cgs.clientinfo[cent->currentState.clientNum].pClass == PC_ADMIN*/
& &
cent - > currentState . weapon = = WP_VOYAGER_HYPO ) {
return ;
}
if ( ent - > weapon = = WP_GRENADE_LAUNCHER ) {
if ( rpg_tripmines ! = 1 ) {
trap_S_StartSound ( NULL , ent - > number , CHAN_WEAPON , weap - > altFlashSnd ) ;
}
} else {
trap_S_StartSound ( NULL , ent - > number , CHAN_WEAPON , weap - > altFlashSnd ) ;
}
}
}
else
{
if ( weap - > flashSound )
{
if ( ent - > weapon = = WP_GRENADE_LAUNCHER ) {
if ( ( rpg_effectsgun = = 1 ) | | ( rpg_tripmines = = 1 ) ) {
return ;
} else {
trap_S_StartSound ( NULL , ent - > number , CHAN_WEAPON , weap - > flashSound ) ;
}
} else {
trap_S_StartSound ( NULL , ent - > number , CHAN_WEAPON , weap - > flashSound ) ;
}
}
}
}
/*
= = = = = = = = = = = = = = = =
CG_FireSeeker
Caused by an EV_FIRE_WEAPON event
= = = = = = = = = = = = = = = =
*/
void CG_FireSeeker ( centity_t * cent )
{
entityState_t * ent ;
weaponInfo_t * weap ;
ent = & cent - > currentState ;
weap = & cg_weapons [ WP_COFFEE ] ;
trap_S_StartSound ( NULL , ent - > number , CHAN_WEAPON , weap - > flashSound ) ;
}
/*
= = = = = = = = = = = = = = = = =
CG_MissileHitWall
Caused by an EV_MISSILE_MISS event , or directly by local bullet tracing
= = = = = = = = = = = = = = = = =
*/
void CG_MissileHitWall ( centity_t * cent , int weapon , vec3_t origin , vec3_t dir )
{
qhandle_t mod ;
qhandle_t mark ;
qhandle_t shader ;
sfxHandle_t sfx ;
float radius ;
float light ;
vec3_t lightColor ;
localEntity_t * le ;
qboolean isSprite ;
int duration ;
qboolean alphaFade ;
// weaponInfo_t *weaponInfo = &cg_weapons[weapon];
mark = 0 ;
radius = 32 ;
sfx = 0 ;
mod = 0 ;
shader = 0 ;
light = 0 ;
lightColor [ 0 ] = 1 ;
lightColor [ 1 ] = 1 ;
lightColor [ 2 ] = 0 ;
// set defaults
isSprite = qfalse ;
duration = 600 ;
switch ( weapon ) {
default :
case WP_PHASER :
// no explosion at LG impact, it is added with the beam
mark = cgs . media . holeMarkShader ;
radius = 12 ;
break ;
case WP_DERMAL_REGEN :
// no explosion at LG impact, it is added with the beam
mark = cgs . media . holeMarkShader ;
radius = 12 ;
break ;
case WP_GRENADE_LAUNCHER :
FX_GrenadeExplode ( origin , dir ) ;
return ;
break ;
case WP_DISRUPTOR :
FX_StasisWeaponHitWall ( origin , dir , 2 ) ; //cent->currentState.time2
return ;
break ;
case WP_NULL_HAND :
/*mod = cgs.media.ringFlashModel;
shader = cgs . media . imodExplosionShader ;
mark = cgs . media . energyMarkShader ;
radius = 24 ; */
break ;
case WP_COMPRESSION_RIFLE :
//mod = cgs.media.ringFlashModel;
//shader = cgs.media.imodExplosionShader;
//mark = cgs.media.energyMarkShader;
//radius = 24;
FX_CompressionExplosion ( cent - > lerpOrigin , origin , dir , qfalse ) ;
return ;
break ;
case WP_TR116 :
//FX_TetrionAltHitWall( origin, dir );
return ;
break ;
/* case WP_COFFEE:
if ( cent - > currentState . eFlags & EF_ALT_FIRING )
{
FX_ScavengerAltExplode ( origin , dir ) ;
}
else
{
FX_ScavengerWeaponHitWall ( origin , dir , qfalse ) ;
}
return ;
break ; */
/* case WP_MEDKIT:
if ( ! ( cent - > currentState . eFlags & EF_ALT_FIRING ) )
{
FX_BorgWeaponHitWall ( origin , dir ) ;
}
return ;
break ; */
case WP_QUANTUM_BURST :
if ( cent - > currentState . eFlags & EF_ALT_FIRING )
{
FX_QuantumAltHitWall ( origin , dir ) ;
}
else
{
FX_QuantumHitWall ( origin , dir ) ;
}
return ;
break ;
}
if ( sfx ) {
trap_S_StartSound ( origin , ENTITYNUM_WORLD , CHAN_AUTO , sfx ) ;
}
//
// create the explosion
//
if ( mod ) {
le = CG_MakeExplosion ( origin , dir ,
mod , shader ,
duration , 1 , isSprite ) ;
le - > light = light ;
VectorCopy ( lightColor , le - > lightColor ) ;
}
//
// impact mark
//
alphaFade = ( mark = = cgs . media . energyMarkShader ) ; // plasma fades alpha, all others fade color
CG_ImpactMark ( mark , origin , dir , random ( ) * 360 , 1 , 1 , 1 , 1 , alphaFade , radius , qfalse ) ;
}
/*
= = = = = = = = = = = = = = = = =
CG_MissileHitPlayer
= = = = = = = = = = = = = = = = =
*/
void CG_MissileHitPlayer ( centity_t * cent , int weapon , vec3_t origin , vec3_t dir )
{
if ( cent )
{ // Showing blood is a no-no.
// CG_Bleed( origin, cent->currentState.otherEntityNum );
}
CG_MissileHitWall ( cent , weapon , origin , dir ) ;
}
/*
= = = = = = = = = = = = = = = = =
CG_BounceEffect
Caused by an EV_BOUNCE | EV_BOUNCE_HALF event
= = = = = = = = = = = = = = = = =
*/
// big fixme. none of these sounds should be registered at runtime
void CG_BounceEffect ( centity_t * cent , int weapon , vec3_t origin , vec3_t normal )
{
int rpg_tripmines ;
const char * info ;
switch ( weapon )
{
case WP_GRENADE_LAUNCHER :
info = CG_ConfigString ( CS_SERVERINFO ) ;
rpg_tripmines = atoi ( Info_ValueForKey ( info , " rpg_invisibletripmines " ) ) ;
if ( rpg_tripmines ! = 1 ) {
if ( rand ( ) & 1 ) {
trap_S_StartSound ( origin , ENTITYNUM_WORLD , CHAN_AUTO , trap_S_RegisterSound ( SOUND_DIR " glauncher/bounce1.wav " ) ) ;
} else {
trap_S_StartSound ( origin , ENTITYNUM_WORLD , CHAN_AUTO , trap_S_RegisterSound ( SOUND_DIR " glauncher/bounce2.wav " ) ) ;
}
}
break ;
case WP_TR116 :
//trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, trap_S_RegisterSound ( va(SOUND_DIR "tetrion/ricochet%d.wav", irandom(1, 3)) ) );
//FX_TetrionRicochet( origin, normal );
break ;
default :
if ( rand ( ) & 1 ) {
trap_S_StartSound ( origin , ENTITYNUM_WORLD , CHAN_AUTO , trap_S_RegisterSound ( SOUND_DIR " glauncher/bounce1.wav " ) ) ;
} else {
trap_S_StartSound ( origin , ENTITYNUM_WORLD , CHAN_AUTO , trap_S_RegisterSound ( SOUND_DIR " glauncher/bounce2.wav " ) ) ;
}
break ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
BULLETS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = = = = = =
CG_CalcMuzzlePoint
= = = = = = = = = = = = = = = = = = = = = =
*/
extern qboolean PM_PlayerCrouching ( int legsAnim ) ;
qboolean CG_CalcMuzzlePoint ( centity_t * cent , vec3_t muzzle , qboolean isDecoy ) {
vec3_t forward ;
//centity_t *cent;
int anim ;
/*if ( entityNum == cg.snap->ps.clientNum && !isDecoy ) {
VectorCopy ( cg . snap - > ps . origin , muzzle ) ;
muzzle [ 2 ] + = cg . snap - > ps . viewheight ;
AngleVectors ( cg . snap - > ps . viewangles , forward , NULL , NULL ) ;
VectorMA ( muzzle , 14 , forward , muzzle ) ;
return qtrue ;
} */
//cent = &cg_entities[entityNum];
if ( ! cent - > currentValid ) {
return qfalse ;
}
//if ( !isDecoy )
VectorCopy ( cent - > currentState . pos . trBase , muzzle ) ;
//else
// VectorCopy( cent->currentState.origin, muzzle );
AngleVectors ( cent - > currentState . apos . trBase , forward , NULL , NULL ) ;
anim = cent - > currentState . legsAnim & ~ ANIM_TOGGLEBIT ;
if ( PM_PlayerCrouching ( cent - > currentState . legsAnim ) ) {
muzzle [ 2 ] + = CROUCH_VIEWHEIGHT ;
} else {
muzzle [ 2 ] + = DEFAULT_VIEWHEIGHT ;
}
VectorMA ( muzzle , 14 , forward , muzzle ) ;
return qtrue ;
}
/*
= = = = = = = = = = = = = = = =
CG_SurfaceExplosion
Adds an explosion to a surface
= = = = = = = = = = = = = = = =
*/
# define NUM_SPARKS 12
# define NUM_PUFFS 1
# define NUM_EXPLOSIONS 4
void CG_SurfaceExplosion ( vec3_t origin , vec3_t normal , float radius , float shake_speed , qboolean smoke )
{
localEntity_t * le ;
vec3_t direction , new_org ;
vec3_t sprayvel , velocity = { 0 , 0 , 0 } ;
vec3_t temp_org , temp_vel ;
float scale , dscale ;
int i , numSparks ;
//Sparks
numSparks = 32 + ( random ( ) * 16.0f ) ;
//VectorSet( normal, 0, 0, 1 );
for ( i = 0 ; i < numSparks ; i + + )
{
scale = 0.25f + ( random ( ) * 2.0f ) ;
dscale = - scale * 0.5 ;
FXE_Spray ( normal , 500 , 150 , 1.0f , sprayvel ) ;
FX_AddTrail ( origin ,
sprayvel ,
qtrue ,
32.0f ,
- 64.0f ,
scale ,
- scale ,
1.0f ,
0.0f ,
0.25f ,
4000.0f ,
cgs . media . sparkShader ) ;
}
//Smoke
//Move this out a little from the impact surface
VectorMA ( origin , 4 , normal , new_org ) ;
VectorSet ( velocity , 0.0f , 0.0f , 16.0f ) ;
for ( i = 0 ; i < 4 ; i + + )
{
VectorSet ( temp_org , new_org [ 0 ] + ( crandom ( ) * 16.0f ) , new_org [ 1 ] + ( crandom ( ) * 16.0f ) , new_org [ 2 ] + ( random ( ) * 4.0f ) ) ;
VectorSet ( temp_vel , velocity [ 0 ] + ( crandom ( ) * 8.0f ) , velocity [ 1 ] + ( crandom ( ) * 8.0f ) , velocity [ 2 ] + ( crandom ( ) * 8.0f ) ) ;
FX_AddSprite ( temp_org ,
temp_vel ,
qfalse ,
radius /**96.0f*/ + ( random ( ) * 12.0f ) ,
16.0f ,
1.0f ,
0.0f ,
20.0f + ( crandom ( ) * 90.0f ) ,
0.5f ,
2000.0f ,
cgs . media . smokeShader ) ;
}
//Core of the explosion
//Orient the explosions to face the camera
VectorSubtract ( cg . refdef . vieworg , origin , direction ) ;
VectorNormalize ( direction ) ;
//Tag the last one with a light
le = CG_MakeExplosion2 ( origin , direction , cgs . media . explosionModel , 5 , cgs . media . surfaceExplosionShader ,
500 , qfalse , radius * 0.02f + ( random ( ) * 0.3f ) , LEF_NONE ) ;
le - > light = 150 ;
VectorSet ( le - > lightColor , 0.9f , 0.8f , 0.5f ) ;
for ( i = 0 ; i < NUM_EXPLOSIONS - 1 ; i + + )
{
VectorSet ( new_org , ( origin [ 0 ] + ( 32 + ( crandom ( ) * 8 ) ) * crandom ( ) ) , ( origin [ 1 ] + ( 32 + ( crandom ( ) * 8 ) ) * crandom ( ) ) , ( origin [ 2 ] + ( 32 + ( crandom ( ) * 8 ) ) * crandom ( ) ) ) ;
le = CG_MakeExplosion2 ( new_org , direction , cgs . media . explosionModel , 5 , cgs . media . surfaceExplosionShader ,
300 + ( rand ( ) & 99 ) , qfalse , radius * 0.05f + ( crandom ( ) * 0.3f ) , LEF_NONE ) ;
}
//Shake the camera
CG_ExplosionEffects ( origin , shake_speed , 350 ) ;
}
void CG_PlayShooterSound ( centity_t * cent ) {
weaponInfo_t * weap ;
weap = & cg_weapons [ cent - > currentState . eventParm ] ;
switch ( cent - > currentState . eventParm ) {
case WP_COMPRESSION_RIFLE :
case WP_GRENADE_LAUNCHER :
case WP_QUANTUM_BURST :
trap_S_StartSound ( cent - > currentState . origin , cent - > currentState . number , CHAN_VOICE , weap - > flashSound ) ;
break ;
case WP_DISRUPTOR :
trap_S_StartSound ( cent - > currentState . origin , cent - > currentState . number , CHAN_VOICE , weap - > altFlashSnd ) ;
break ;
}
}