summaryrefslogtreecommitdiff
path: root/src/cgame
diff options
context:
space:
mode:
authorMichael Levin <risujin@fastmail.fm>2009-10-03 11:26:51 +0000
committerTim Angus <tim@ngus.net>2013-01-03 00:15:00 +0000
commit0cf04fe37fef2e827a95bb19926a3cbf8e98c581 (patch)
tree93ac01309f47edb27be26fb31e3886f6082579b1 /src/cgame
parentd9709deb95375f2462e5ca9fc98ebf92fd91ce04 (diff)
* Added charge meter to the UI, can be disabled via GUI
* Trample and Lucifer Cannon charging reworked and moved to PMove * Can no longer "cancel" a charging Lucifer Cannon * STAT_MISC2 is now unused, booster and charge information can be inferred elsewhere (STAT_UNUSED) * Trying to fire an empty weapon makes a clicking noise (also a bugfix, apparently the server would spam EV_NOAMMO which did nothing but is now used for the clicking noise -- audible to all players) * Created an alternate, muffled Lucifer Cannon warning noise for other people's Lucifer Cannons * Fixed bug which prevented players from switching to a different player while spectating someone in the spawn queue * Spectators are now properly moved to the lock view position when spectating a player in the spawn queue
Diffstat (limited to 'src/cgame')
-rw-r--r--src/cgame/cg_draw.c141
-rw-r--r--src/cgame/cg_event.c4
-rw-r--r--src/cgame/cg_local.h8
-rw-r--r--src/cgame/cg_main.c6
-rw-r--r--src/cgame/cg_view.c2
-rw-r--r--src/cgame/cg_weapons.c33
6 files changed, 158 insertions, 36 deletions
diff --git a/src/cgame/cg_draw.c b/src/cgame/cg_draw.c
index 08433c44..5002fc9a 100644
--- a/src/cgame/cg_draw.c
+++ b/src/cgame/cg_draw.c
@@ -588,21 +588,15 @@ CG_DrawPlayerBoosterBolt
*/
static void CG_DrawPlayerBoosterBolt( rectDef_t *rect, vec4_t color, qhandle_t shader )
{
- vec4_t localColor;
- playerState_t *ps = &cg.snap->ps;
+ vec4_t localColor;
Vector4Copy( color, localColor );
- if( ps->stats[ STAT_STATE ] & SS_BOOSTED )
- {
- if( ps->stats[ STAT_MISC2 ] < 3000 )
- {
- qboolean flash = ( ps->stats[ STAT_MISC2 ] / 500 ) % 2;
-
- if( flash )
- localColor[ 3 ] = 1.0f;
- }
- }
+ // Flash bolts when the boost is almost out
+ if( ( cg.snap->ps.stats[ STAT_STATE ] & SS_BOOSTED ) &&
+ cg.boostedTime > 0 && cg.time - cg.boostedTime > BOOST_TIME - 5000 &&
+ cg.time & 256 )
+ localColor[ 3 ] = 1.0f;
trap_R_SetColor( localColor );
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
@@ -904,6 +898,123 @@ static void CG_DrawPlayerHealthCross3( rectDef_t *rect, vec4_t color, qhandle_t
trap_R_SetColor( NULL );
}
+static float CG_ChargeProgress( void )
+{
+ float progress;
+ int min = 0, max = 0;
+
+ if( cg.snap->ps.weapon == WP_ALEVEL3 )
+ {
+ min = LEVEL3_POUNCE_TIME_MIN;
+ max = LEVEL3_POUNCE_TIME;
+ }
+ else if( cg.snap->ps.weapon == WP_ALEVEL3_UPG )
+ {
+ min = LEVEL3_POUNCE_TIME_MIN;
+ max = LEVEL3_POUNCE_TIME_UPG;
+ }
+ else if( cg.snap->ps.weapon == WP_ALEVEL4 )
+ {
+ min = LEVEL4_TRAMPLE_CHARGE_MIN;
+ max = LEVEL4_TRAMPLE_CHARGE_MAX;
+ }
+ else if( cg.snap->ps.weapon == WP_LUCIFER_CANNON )
+ {
+ min = LCANNON_CHARGE_TIME_MIN;
+ max = LCANNON_CHARGE_TIME_MAX;
+ }
+ if( max - min < 0.0f )
+ return 0.0f;
+ progress = ( (float)cg.predictedPlayerState.stats[ STAT_MISC ] - min ) /
+ ( max - min );
+ if( progress > 1.0f )
+ return 1.0f;
+ if( progress < 0.0f )
+ return 0.0f;
+ return progress;
+}
+
+#define CHARGE_BAR_FADE_RATE 0.002f
+
+static void CG_DrawPlayerChargeBarBG( rectDef_t *rect, vec4_t ref_color,
+ qhandle_t shader )
+{
+ vec4_t color;
+
+ if( !cg_drawChargeBar.integer || cg.chargeMeterAlpha <= 0.0f )
+ return;
+
+ color[ 0 ] = ref_color[ 0 ];
+ color[ 1 ] = ref_color[ 1 ];
+ color[ 2 ] = ref_color[ 2 ];
+ color[ 3 ] = ref_color[ 3 ] * cg.chargeMeterAlpha;
+
+ // Draw meter background
+ trap_R_SetColor( color );
+ CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
+ trap_R_SetColor( NULL );
+}
+
+static void CG_DrawPlayerChargeBar( rectDef_t *rect, vec4_t ref_color,
+ qhandle_t shader )
+{
+ vec4_t color;
+ float x, y, width, height, cap_width, progress;
+
+ if( !cg_drawChargeBar.integer )
+ return;
+
+ // Get progress proportion and pump fade
+ progress = CG_ChargeProgress();
+ if( progress <= 0.0f )
+ {
+ cg.chargeMeterAlpha -= CHARGE_BAR_FADE_RATE * cg.frametime;
+ if( cg.chargeMeterAlpha <= 0.0f )
+ {
+ cg.chargeMeterAlpha = 0.0f;
+ return;
+ }
+ }
+ else
+ {
+ cg.chargeMeterValue = progress;
+ cg.chargeMeterAlpha += CHARGE_BAR_FADE_RATE * cg.frametime;
+ if( cg.chargeMeterAlpha > 1.0f )
+ cg.chargeMeterAlpha = 1.0f;
+ }
+
+ color[ 0 ] = ref_color[ 0 ];
+ color[ 1 ] = ref_color[ 1 ];
+ color[ 2 ] = ref_color[ 2 ];
+ color[ 3 ] = ref_color[ 3 ] * cg.chargeMeterAlpha;
+
+ // Flash red for Lucifer Cannon warning
+ if( cg.snap->ps.weapon == WP_LUCIFER_CANNON &&
+ cg.snap->ps.stats[ STAT_MISC ] >= LCANNON_CHARGE_TIME_WARN &&
+ ( cg.time & 128 ) )
+ {
+ color[ 0 ] = 1.0f;
+ color[ 1 ] = 0.0f;
+ color[ 2 ] = 0.0f;
+ }
+
+ // Calculate bar coords
+ x = rect->x;
+ y = rect->y;
+ width = ( rect->w - 6 ) * cg.chargeMeterValue;
+ height = rect->h;
+ CG_AdjustFrom640( &x, &y, &width, &height );
+ cap_width = 3 * cgs.screenXScale;
+
+ // Draw the meter
+ trap_R_SetColor( color );
+ trap_R_DrawStretchPic( x, y, cap_width, height, 0, 0, 1, 1, shader );
+ trap_R_DrawStretchPic( x + width + cap_width, y, cap_width, height,
+ 1, 0, 0, 1, shader );
+ trap_R_DrawStretchPic( x + cap_width, y, width, height, 1, 0, 1, 1, shader );
+ trap_R_SetColor( NULL );
+}
+
static void CG_DrawProgressLabel( rectDef_t *rect, float text_x, float text_y, vec4_t color,
float scale, int textalign, int textvalign,
const char *s, float fraction )
@@ -2151,6 +2262,12 @@ void CG_OwnerDraw( float x, float y, float w, float h, float text_x,
case CG_PLAYER_HEALTH_CROSS3:
CG_DrawPlayerHealthCross3( &rect, color, shader );
break;
+ case CG_PLAYER_CHARGE_BAR_BG:
+ CG_DrawPlayerChargeBarBG( &rect, color, shader );
+ break;
+ case CG_PLAYER_CHARGE_BAR:
+ CG_DrawPlayerChargeBar( &rect, color, shader );
+ break;
case CG_PLAYER_CLIPS_RING:
CG_DrawPlayerClipsRing( &rect, color, shader );
break;
diff --git a/src/cgame/cg_event.c b/src/cgame/cg_event.c
index 9b6afbe6..2d622088 100644
--- a/src/cgame/cg_event.c
+++ b/src/cgame/cg_event.c
@@ -737,8 +737,8 @@ void CG_EntityEvent( centity_t *cent, vec3_t position )
//
case EV_NOAMMO:
DEBUGNAME( "EV_NOAMMO" );
- {
- }
+ trap_S_StartSound( NULL, es->number, CHAN_WEAPON,
+ cgs.media.weaponEmptyClick );
break;
case EV_CHANGE_WEAPON:
diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h
index 360dac34..8dfd09a4 100644
--- a/src/cgame/cg_local.h
+++ b/src/cgame/cg_local.h
@@ -1133,6 +1133,11 @@ typedef struct
playerState_t savedPmoveStates[ NUM_SAVED_STATES ];
int stateHead, stateTail;
int ping;
+
+ float chargeMeterAlpha;
+ float chargeMeterValue;
+
+ int nextWeaponClickTime;
} cg_t;
@@ -1179,6 +1184,7 @@ typedef struct
// sounds
sfxHandle_t tracerSound;
+ sfxHandle_t weaponEmptyClick;
sfxHandle_t selectSound;
sfxHandle_t footsteps[ FOOTSTEP_TOTAL ][ 4 ];
sfxHandle_t talkSound;
@@ -1263,6 +1269,7 @@ typedef struct
qhandle_t massDriverTS;
sfxHandle_t lCannonWarningSound;
+ sfxHandle_t lCannonWarningSound2;
qhandle_t buildWeaponTimerPie[ 8 ];
qhandle_t upgradeClassIconShader;
@@ -1409,6 +1416,7 @@ extern vmCvar_t cg_drawSnapshot;
extern vmCvar_t cg_draw3dIcons;
extern vmCvar_t cg_drawIcons;
extern vmCvar_t cg_drawAmmoWarning;
+extern vmCvar_t cg_drawChargeBar;
extern vmCvar_t cg_drawCrosshair;
extern vmCvar_t cg_drawCrosshairNames;
extern vmCvar_t cg_drawRewards;
diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c
index ac0715fe..a2027b3e 100644
--- a/src/cgame/cg_main.c
+++ b/src/cgame/cg_main.c
@@ -125,6 +125,7 @@ vmCvar_t cg_drawSnapshot;
vmCvar_t cg_draw3dIcons;
vmCvar_t cg_drawIcons;
vmCvar_t cg_drawAmmoWarning;
+vmCvar_t cg_drawChargeBar;
vmCvar_t cg_drawCrosshair;
vmCvar_t cg_drawCrosshairNames;
vmCvar_t cg_drawRewards;
@@ -268,6 +269,7 @@ static cvarTable_t cvarTable[ ] =
{ &cg_draw3dIcons, "cg_draw3dIcons", "1", CVAR_ARCHIVE },
{ &cg_drawIcons, "cg_drawIcons", "1", CVAR_ARCHIVE },
{ &cg_drawAmmoWarning, "cg_drawAmmoWarning", "1", CVAR_ARCHIVE },
+ { &cg_drawChargeBar, "cg_drawChargeBar", "1", CVAR_ARCHIVE },
{ &cg_drawAttacker, "cg_drawAttacker", "1", CVAR_ARCHIVE },
{ &cg_drawCrosshair, "cg_drawCrosshair", "1", CVAR_ARCHIVE },
{ &cg_drawCrosshairNames, "cg_drawCrosshairNames", "1", CVAR_ARCHIVE },
@@ -692,6 +694,7 @@ static void CG_RegisterSounds( void )
cgs.media.tracerSound = trap_S_RegisterSound( "sound/weapons/tracer.wav", qfalse );
cgs.media.selectSound = trap_S_RegisterSound( "sound/weapons/change.wav", qfalse );
cgs.media.turretSpinupSound = trap_S_RegisterSound( "sound/buildables/mgturret/spinup.wav", qfalse );
+ cgs.media.weaponEmptyClick = trap_S_RegisterSound( "sound/weapons/click.wav", qfalse );
cgs.media.talkSound = trap_S_RegisterSound( "sound/misc/talk.wav", qfalse );
cgs.media.alienTalkSound = trap_S_RegisterSound( "sound/misc/alien_talk.wav", qfalse );
@@ -760,6 +763,7 @@ static void CG_RegisterSounds( void )
cgs.media.buildableRepairedSound = trap_S_RegisterSound( "sound/buildables/human/repaired.wav", qfalse );
cgs.media.lCannonWarningSound = trap_S_RegisterSound( "models/weapons/lcannon/warning.wav", qfalse );
+ cgs.media.lCannonWarningSound2 = trap_S_RegisterSound( "models/weapons/lcannon/warning2.wav", qfalse );
}
@@ -835,7 +839,7 @@ static void CG_RegisterGraphics( void )
cgs.media.buildWeaponTimerPie[ i ] = trap_R_RegisterShader( buildWeaponTimerPieShaders[ i ] );
cgs.media.upgradeClassIconShader = trap_R_RegisterShader( "icons/icona_upgrade.tga" );
-
+
cgs.media.balloonShader = trap_R_RegisterShader( "gfx/sprites/chatballoon" );
cgs.media.disconnectPS = CG_RegisterParticleSystem( "disconnectPS" );
diff --git a/src/cgame/cg_view.c b/src/cgame/cg_view.c
index 2c718556..9772e1f5 100644
--- a/src/cgame/cg_view.c
+++ b/src/cgame/cg_view.c
@@ -471,7 +471,7 @@ static void CG_OffsetFirstPersonView( void )
if( ps->stats[ STAT_MISC ] > 0 )
{
float fraction = (float)ps->stats[ STAT_MISC ] /
- (float)LEVEL4_TRAMPLE_CHARGE_MAX;
+ LEVEL4_TRAMPLE_CHARGE_MAX;
if( fraction > 1.0f )
fraction = 1.0f;
diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c
index f4c8fbf8..d0968dd9 100644
--- a/src/cgame/cg_weapons.c
+++ b/src/cgame/cg_weapons.c
@@ -872,8 +872,9 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
// Lucifer cannon charge warning beep
if( weaponNum == WP_LUCIFER_CANNON &&
( cent->currentState.eFlags & EF_WARN_CHARGE ) )
- trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin,
- vec3_origin, cgs.media.lCannonWarningSound );
+ trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin,
+ vec3_origin, ps ? cgs.media.lCannonWarningSound :
+ cgs.media.lCannonWarningSound2 );
if( !noGunModel )
{
@@ -987,6 +988,9 @@ CG_AddViewWeapon
Add the weapon, and flash for the player's view
==============
*/
+
+#define WEAPON_CLICK_REPEAT 500
+
void CG_AddViewWeapon( playerState_t *ps )
{
refEntity_t hand;
@@ -1072,27 +1076,16 @@ void CG_AddViewWeapon( playerState_t *ps )
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 );
- if( weapon == WP_LUCIFER_CANNON )
+ // Lucifer Cannon vibration effect
+ if( weapon == WP_LUCIFER_CANNON && ps->stats[ STAT_MISC ] > 0 )
{
float fraction;
- if( ps->stats[ STAT_MISC ] > 0 )
- {
- // vibration effect
- fraction = (float)ps->stats[ STAT_MISC ] / (float)LCANNON_TOTAL_CHARGE;
- VectorMA( hand.origin, random( ) * fraction, cg.refdef.viewaxis[ 0 ],
- hand.origin );
- VectorMA( hand.origin, random( ) * fraction, cg.refdef.viewaxis[ 1 ],
- hand.origin );
- }
- else if( ps->stats[ STAT_MISC2 ] > 0 )
- {
- // reloading effect
- fraction = (float)ps->stats[ STAT_MISC2 ] / 250.0f;
- fraction = ( fraction > 1.0f ) ? 1.0f : fraction;
- VectorMA( hand.origin, fraction * -3.0f, cg.refdef.viewaxis[ 2 ],
- hand.origin );
- }
+ fraction = (float)ps->stats[ STAT_MISC ] / LCANNON_CHARGE_TIME_MAX;
+ VectorMA( hand.origin, random( ) * fraction, cg.refdef.viewaxis[ 0 ],
+ hand.origin );
+ VectorMA( hand.origin, random( ) * fraction, cg.refdef.viewaxis[ 1 ],
+ hand.origin );
}
AnglesToAxis( angles, hand.axis );