📄 cg_weapons.c
字号:
==============
*/
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 ) {
return;
}
if ( ps->pm_type == PM_INTERMISSION ) {
return;
}
// no gun if in third person view or a camera is active
//if ( cg.renderingThirdPerson || cg.cameraMode) {
if ( cg.renderingThirdPerson ) {
return;
}
// allow the gun to be completely removed
if ( !cg_drawGun.integer ) {
vec3_t origin;
if ( cg.predictedPlayerState.eFlags & EF_FIRING ) {
// special hack for lightning gun...
VectorCopy( cg.refdef.vieworg, origin );
VectorMA( origin, -8, cg.refdef.viewaxis[2], origin );
CG_LightningBolt( &cg_entities[ps->clientNum], origin );
}
return;
}
// don't draw if testing a gun model
if ( cg.testGun ) {
return;
}
// drop gun lower at higher fov
if ( cg_fov.integer > 90 ) {
fovOffset = -0.2 * ( cg_fov.integer - 90 );
} 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 | RF_MINLIGHT;
// add everything onto the hand
CG_AddPlayerWeapon( &hand, ps, &cg.predictedPlayerEntity, ps->persistant[PERS_TEAM] );
}
/*
==============================================================================
WEAPON SELECTION
==============================================================================
*/
/*
===================
CG_DrawWeaponSelect
===================
*/
void CG_DrawWeaponSelect( void ) {
int i;
int bits;
int count;
int x, y, w;
char *name;
float *color;
// don't display if dead
if ( cg.predictedPlayerState.stats[STAT_HEALTH] <= 0 ) {
return;
}
color = CG_FadeColor( cg.weaponSelectTime, WEAPON_SELECT_TIME );
if ( !color ) {
return;
}
trap_R_SetColor( color );
// 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 ];
count = 0;
for ( i = 1 ; i < 16 ; i++ ) {
if ( bits & ( 1 << i ) ) {
count++;
}
}
x = 320 - count * 20;
y = 380;
for ( i = 1 ; i < 16 ; i++ ) {
if ( !( bits & ( 1 << i ) ) ) {
continue;
}
CG_RegisterWeapon( i );
// draw weapon icon
CG_DrawPic( x, y, 32, 32, cg_weapons[i].weaponIcon );
// draw selection marker
if ( i == cg.weaponSelect ) {
CG_DrawPic( x-4, y-4, 40, 40, cgs.media.selectShader );
}
// no ammo cross on top
if ( !cg.snap->ps.ammo[ i ] ) {
CG_DrawPic( x, y, 32, 32, cgs.media.noammoShader );
}
x += 40;
}
// draw the selected name
if ( cg_weapons[ cg.weaponSelect ].item ) {
name = cg_weapons[ cg.weaponSelect ].item->pickup_name;
if ( name ) {
w = CG_DrawStrlen( name ) * BIGCHAR_WIDTH;
x = ( SCREEN_WIDTH - w ) / 2;
CG_DrawBigStringColor(x, y - 22, name, 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;
}
/*
===============
CG_NextWeapon_f
===============
*/
void CG_NextWeapon_f( void ) {
int i;
int original;
if ( !cg.snap ) {
return;
}
if ( cg.snap->ps.pm_flags & PMF_FOLLOW ) {
return;
}
cg.weaponSelectTime = cg.time;
original = cg.weaponSelect;
for ( i = 0 ; i < 16 ; i++ ) {
cg.weaponSelect++;
if ( cg.weaponSelect == 16 ) {
cg.weaponSelect = 0;
}
if ( cg.weaponSelect == WP_GAUNTLET ) {
continue; // never cycle to gauntlet
}
if ( CG_WeaponSelectable( cg.weaponSelect ) ) {
break;
}
}
if ( i == 16 ) {
cg.weaponSelect = original;
}
}
/*
===============
CG_PrevWeapon_f
===============
*/
void CG_PrevWeapon_f( void ) {
int i;
int original;
if ( !cg.snap ) {
return;
}
if ( cg.snap->ps.pm_flags & PMF_FOLLOW ) {
return;
}
cg.weaponSelectTime = cg.time;
original = cg.weaponSelect;
for ( i = 0 ; i < 16 ; i++ ) {
cg.weaponSelect--;
if ( cg.weaponSelect == -1 ) {
cg.weaponSelect = 15;
}
if ( cg.weaponSelect == WP_GAUNTLET ) {
continue; // never cycle to gauntlet
}
if ( CG_WeaponSelectable( cg.weaponSelect ) ) {
break;
}
}
if ( i == 16 ) {
cg.weaponSelect = original;
}
}
/*
===============
CG_Weapon_f
===============
*/
void CG_Weapon_f( void ) {
int num;
if ( !cg.snap ) {
return;
}
if ( cg.snap->ps.pm_flags & PMF_FOLLOW ) {
return;
}
num = atoi( CG_Argv( 1 ) );
if ( num < 1 || num > 15 ) {
return;
}
cg.weaponSelectTime = cg.time;
if ( ! ( cg.snap->ps.stats[STAT_WEAPONS] & ( 1 << num ) ) ) {
return; // don't have the weapon
}
cg.weaponSelect = num;
}
/*
===================
CG_OutOfAmmoChange
The current weapon has just run out of ammo
===================
*/
void CG_OutOfAmmoChange( void ) {
int i;
cg.weaponSelectTime = cg.time;
for ( i = 15 ; i > 0 ; i-- ) {
if ( CG_WeaponSelectable( i ) ) {
cg.weaponSelect = i;
break;
}
}
}
/*
===================================================================================================
WEAPON EVENTS
===================================================================================================
*/
/*
================
CG_FireWeapon
Caused by an EV_FIRE_WEAPON event
================
*/
void CG_FireWeapon( centity_t *cent ) {
entityState_t *ent;
int c;
weaponInfo_t *weap;
ent = ¢->currentState;
if ( ent->weapon == WP_NONE ) {
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_LIGHTNING ) {
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
for ( c = 0 ; c < 4 ; c++ ) {
if ( !weap->flashSound[c] ) {
break;
}
}
if ( c > 0 ) {
c = rand() % c;
if ( weap->flashSound[c] )
{
trap_S_StartSound( NULL, ent->number, CHAN_WEAPON, weap->flashSound[c] );
}
}
// do brass ejection
if ( weap->ejectBrassFunc && cg_brassTime.integer > 0 ) {
weap->ejectBrassFunc( cent );
}
}
/*
=================
CG_MissileHitWall
Caused by an EV_MISSILE_MISS event, or directly by local bullet tracing
=================
*/
void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, impactSound_t soundType ) {
qhandle_t mod;
qhandle_t mark;
qhandle_t shader;
sfxHandle_t sfx;
float radius;
float light;
vec3_t lightColor;
localEntity_t *le;
int r;
qboolean alphaFade;
qboolean isSprite;
int duration;
vec3_t sprOrg;
vec3_t sprVel;
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:
#ifdef MISSIONPACK
case WP_NAILGUN:
if( soundType == IMPACTSOUND_FLESH ) {
sfx = cgs.media.sfx_nghitflesh;
} else if( soundType == IMPACTSOUND_METAL ) {
sfx = cgs.media.sfx_nghitmetal;
} else {
sfx = cgs.media.sfx_nghit;
}
mark = cgs.media.holeMarkShader;
radius = 12;
break;
#endif
case WP_LIGHTNING:
// no explosion at LG impact, it is added with the beam
r = rand() & 3;
if ( r < 2 ) {
sfx = cgs.media.sfx_lghit2;
} else if ( r == 2 ) {
sfx = cgs.media.sfx_lghit1;
} else {
sfx = cgs.media.sfx_lghit3;
}
mark = cgs.media.holeMarkShader;
radius = 12;
break;
#ifdef MISSIONPACK
case WP_PROX_LAUNCHER:
mod = cgs.media.dishFlashModel;
shader = cgs.media.grenadeExplosionShader;
sfx = cgs.media.sfx_proxexp;
mark = cgs.media.burnMarkShader;
radius = 64;
light = 300;
isSprite = qtrue;
break;
#endif
case WP_GRENADE_LAUNCHER:
mod = cgs.media.dishFlashModel;
shader = cgs.media.grenadeExplosionShader;
sfx = cgs.media.sfx_rockexp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -