summaryrefslogtreecommitdiff
path: root/src/cgame
diff options
context:
space:
mode:
Diffstat (limited to 'src/cgame')
-rw-r--r--src/cgame/cg_buildable.c7
-rw-r--r--src/cgame/cg_consolecmds.c8
-rw-r--r--src/cgame/cg_draw.c11
-rw-r--r--src/cgame/cg_ents.c104
-rw-r--r--src/cgame/cg_event.c100
-rw-r--r--src/cgame/cg_local.h3
-rw-r--r--src/cgame/cg_main.c9
-rw-r--r--src/cgame/cg_public.h6
-rw-r--r--src/cgame/cg_tutorial.c38
-rw-r--r--src/cgame/cg_view.c19
-rw-r--r--src/cgame/cg_weapons.c23
11 files changed, 206 insertions, 122 deletions
diff --git a/src/cgame/cg_buildable.c b/src/cgame/cg_buildable.c
index b8d03a48..0a1f3877 100644
--- a/src/cgame/cg_buildable.c
+++ b/src/cgame/cg_buildable.c
@@ -904,6 +904,7 @@ static void CG_BuildableStatusDisplay( centity_t *cent )
qboolean visible = qfalse;
vec3_t mins, maxs;
entityState_t *hit;
+ int anim;
if( BG_FindTeamForBuildable( es->modelindex ) == BIT_ALIENS )
bs = &cgs.alienBuildStat;
@@ -922,6 +923,12 @@ static void CG_BuildableStatusDisplay( centity_t *cent )
// trace for center point
BG_FindBBoxForBuildable( es->modelindex, mins, maxs );
+ // hack for shrunken barricades
+ anim = es->torsoAnim & ~( ANIM_FORCEBIT | ANIM_TOGGLEBIT );
+ if( es->modelindex == BA_A_BARRICADE &&
+ ( anim == BANIM_DESTROYED || !( es->generic1 & B_SPAWNED_TOGGLEBIT ) ) )
+ maxs[ 2 ] = (int)( maxs[ 2 ] * BARRICADE_SHRINKPROP );
+
VectorCopy( cent->lerpOrigin, origin );
// center point
diff --git a/src/cgame/cg_consolecmds.c b/src/cgame/cg_consolecmds.c
index a44a5497..697b0e98 100644
--- a/src/cgame/cg_consolecmds.c
+++ b/src/cgame/cg_consolecmds.c
@@ -279,10 +279,10 @@ void CG_InitConsoleCommands( void )
// forwarded to the server after they are not recognized locally
//
trap_AddCommand( "kill" );
- trap_AddCommand( "messagemode" );
- trap_AddCommand( "messagemode2" );
- trap_AddCommand( "messagemode3" );
- trap_AddCommand( "messagemode4" );
+ trap_AddCommand( "ui_messagemode" );
+ trap_AddCommand( "ui_messagemode2" );
+ trap_AddCommand( "ui_messagemode3" );
+ trap_AddCommand( "ui_messagemode4" );
trap_AddCommand( "say" );
trap_AddCommand( "say_team" );
trap_AddCommand( "tell" );
diff --git a/src/cgame/cg_draw.c b/src/cgame/cg_draw.c
index 47e7d477..c8f75da0 100644
--- a/src/cgame/cg_draw.c
+++ b/src/cgame/cg_draw.c
@@ -593,14 +593,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;
Vector4Copy( color, localColor );
- if( cg.boostedTime >= 0 )
+ if( ps->stats[ STAT_STATE ] & SS_BOOSTED )
{
- if( ( cg.time - cg.boostedTime ) > BOOST_TIME - 3000 )
+ if( ps->stats[ STAT_MISC2 ] < 3000 )
{
- qboolean flash = ( cg.time / 500 ) % 2;
+ qboolean flash = ( ps->stats[ STAT_MISC2 ] / 500 ) % 2;
if( flash )
localColor[ 3 ] = 1.0f;
@@ -1986,7 +1987,7 @@ static void CG_DrawCrosshair( void )
wi = &cg_weapons[ cg.snap->ps.weapon ];
- w = h = wi->crossHairSize;
+ w = h = wi->crossHairSize * cg_crosshairSize.value;
w *= cgDC.aspectScale;
@@ -3017,5 +3018,3 @@ void CG_DrawActive( stereoFrame_t stereoView )
CG_Draw2D( );
}
-
-
diff --git a/src/cgame/cg_ents.c b/src/cgame/cg_ents.c
index 17f1a7d3..c6597b6b 100644
--- a/src/cgame/cg_ents.c
+++ b/src/cgame/cg_ents.c
@@ -216,6 +216,8 @@ Add continuous entity effects, like local entity emission and lighting
*/
static void CG_EntityEffects( centity_t *cent )
{
+ int i;
+
// update sound origins
CG_SetEntitySoundPosition( cent );
@@ -251,7 +253,7 @@ static void CG_EntityEffects( centity_t *cent )
if( CG_IsTrailSystemValid( &cent->muzzleTS ) )
{
- //FIXME hack to prevent tesla trails reaching too far
+ //FIXME hack to prevent tesla trails reaching too far
if( cent->currentState.eType == ET_BUILDABLE )
{
vec3_t front, back;
@@ -266,6 +268,33 @@ static void CG_EntityEffects( centity_t *cent )
if( cg.time > cent->muzzleTSDeathTime && CG_IsTrailSystemValid( &cent->muzzleTS ) )
CG_DestroyTrailSystem( &cent->muzzleTS );
}
+
+
+ if( cent->currentState.eType == ET_PLAYER )
+ {
+ centity_t *pcent = cent;;
+
+ // predicted entity doesn't have local cgame vars
+ if( cent == &cg.predictedPlayerEntity )
+ pcent = &cg_entities[ cg.clientNum ];
+
+ for( i = 0; i <= 2; i++ )
+ {
+ if( CG_IsTrailSystemValid( &pcent->level2ZapTS[ i ] ) )
+ {
+ vec3_t front, back;
+
+ CG_AttachmentPoint( &pcent->level2ZapTS[ i ]->frontAttachment, front );
+ CG_AttachmentPoint( &pcent->level2ZapTS[ i ]->backAttachment, back );
+
+ if( cg.time - pcent->level2ZapTime > 100 ||
+ Distance( front, back ) > LEVEL2_AREAZAP_CUTOFF )
+ {
+ CG_DestroyTrailSystem( &pcent->level2ZapTS[ i ] );
+ }
+ }
+ }
+ }
}
@@ -780,61 +809,6 @@ static void CG_LightFlare( centity_t *cent )
/*
=========================
-CG_Lev2ZapChain
-=========================
-*/
-static void CG_Lev2ZapChain( centity_t *cent )
-{
- int i;
- entityState_t *es;
- centity_t *source = NULL, *target = NULL;
-
- es = &cent->currentState;
-
- for( i = 0; i <= 2; i++ )
- {
- switch( i )
- {
- case 0:
- if( es->time <= 0 )
- continue;
-
- source = &cg_entities[ es->misc ];
- target = &cg_entities[ es->time ];
- break;
-
- case 1:
- if( es->time2 <= 0 )
- continue;
-
- source = &cg_entities[ es->time ];
- target = &cg_entities[ es->time2 ];
- break;
-
- case 2:
- if( es->constantLight <= 0 )
- continue;
-
- source = &cg_entities[ es->time2 ];
- target = &cg_entities[ es->constantLight ];
- break;
- }
-
- if( !CG_IsTrailSystemValid( &cent->level2ZapTS[ i ] ) )
- cent->level2ZapTS[ i ] = CG_SpawnNewTrailSystem( cgs.media.level2ZapTS );
-
- if( CG_IsTrailSystemValid( &cent->level2ZapTS[ i ] ) )
- {
- CG_SetAttachmentCent( &cent->level2ZapTS[ i ]->frontAttachment, source );
- CG_SetAttachmentCent( &cent->level2ZapTS[ i ]->backAttachment, target );
- CG_AttachToCent( &cent->level2ZapTS[ i ]->frontAttachment );
- CG_AttachToCent( &cent->level2ZapTS[ i ]->backAttachment );
- }
- }
-}
-
-/*
-=========================
CG_AdjustPositionForMover
Also called by client movement prediction code
@@ -1029,22 +1003,8 @@ CG_CEntityPVSLeave
*/
static void CG_CEntityPVSLeave( centity_t *cent )
{
- int i;
- entityState_t *es = &cent->currentState;
-
if( cg_debugPVS.integer )
CG_Printf( "Entity %d left PVS\n", cent->currentState.number );
-
- switch( es->eType )
- {
- case ET_LEV2_ZAP_CHAIN:
- for( i = 0; i <= 2; i++ )
- {
- if( CG_IsTrailSystemValid( &cent->level2ZapTS[ i ] ) )
- CG_DestroyTrailSystem( &cent->level2ZapTS[ i ] );
- }
- break;
- }
}
@@ -1128,10 +1088,6 @@ static void CG_AddCEntity( centity_t *cent )
case ET_LIGHTFLARE:
CG_LightFlare( cent );
break;
-
- case ET_LEV2_ZAP_CHAIN:
- CG_Lev2ZapChain( cent );
- break;
}
}
diff --git a/src/cgame/cg_event.c b/src/cgame/cg_event.c
index 454f843e..1caba1f5 100644
--- a/src/cgame/cg_event.c
+++ b/src/cgame/cg_event.c
@@ -168,6 +168,24 @@ static void CG_Obituary( entityState_t *ent )
message = "blew himself up";
break;
+ case MOD_LEVEL3_BOUNCEBALL:
+ if( gender == GENDER_FEMALE )
+ message = "sniped herself";
+ else if( gender == GENDER_NEUTER )
+ message = "sniped itself";
+ else
+ message = "sniped himself";
+ break;
+
+ case MOD_PRIFLE:
+ if( gender == GENDER_FEMALE )
+ message = "pulse rifled herself";
+ else if( gender == GENDER_NEUTER )
+ message = "pulse rifled itself";
+ else
+ message = "pulse rifled himself";
+ break;
+
default:
if( gender == GENDER_FEMALE )
message = "killed herself";
@@ -181,7 +199,7 @@ static void CG_Obituary( entityState_t *ent )
if( message )
{
- CG_Printf( "%s" S_COLOR_WHITE " %s.\n", targetName, message );
+ CG_Printf( "%s" S_COLOR_WHITE " %s\n", targetName, message );
return;
}
@@ -297,12 +315,16 @@ static void CG_Obituary( entityState_t *ent )
BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL4 ) );
message2 = className;
break;
- case MOD_LEVEL4_CHARGE:
+ case MOD_LEVEL4_TRAMPLE:
message = "should have gotten out of the way of";
Com_sprintf( className, 64, "'s %s",
BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL4 ) );
message2 = className;
break;
+ case MOD_LEVEL4_CRUSH:
+ message = "was crushed under";
+ message2 = "'s weight";
+ break;
case MOD_POISON:
message = "should have used a medkit against";
@@ -342,7 +364,7 @@ static void CG_Obituary( entityState_t *ent )
}
// we don't know what it was
- CG_Printf( "%s died.\n", targetName );
+ CG_Printf( "%s died\n", targetName );
}
//==========================================================================
@@ -380,6 +402,60 @@ void CG_PainEvent( centity_t *cent, int health )
}
/*
+=========================
+CG_Level2Zap
+=========================
+*/
+static void CG_Level2Zap( entityState_t *es )
+{
+ int i;
+ centity_t *source = NULL, *target = NULL;
+
+ if( es->misc < 0 || es->misc >= MAX_CLIENTS )
+ return;
+
+ source = &cg_entities[ es->misc ];
+ for( i = 0; i <= 2; i++ )
+ {
+ switch( i )
+ {
+ case 0:
+ if( es->time <= 0 )
+ continue;
+
+ target = &cg_entities[ es->time ];
+ break;
+
+ case 1:
+ if( es->time2 <= 0 )
+ continue;
+
+ target = &cg_entities[ es->time2 ];
+ break;
+
+ case 2:
+ if( es->constantLight <= 0 )
+ continue;
+
+ target = &cg_entities[ es->constantLight ];
+ break;
+ }
+
+ if( !CG_IsTrailSystemValid( &source->level2ZapTS[ i ] ) )
+ source->level2ZapTS[ i ] = CG_SpawnNewTrailSystem( cgs.media.level2ZapTS );
+
+ if( CG_IsTrailSystemValid( &source->level2ZapTS[ i ] ) )
+ {
+ CG_SetAttachmentCent( &source->level2ZapTS[ i ]->frontAttachment, source );
+ CG_SetAttachmentCent( &source->level2ZapTS[ i ]->backAttachment, target );
+ CG_AttachToCent( &source->level2ZapTS[ i ]->frontAttachment );
+ CG_AttachToCent( &source->level2ZapTS[ i ]->backAttachment );
+ }
+ }
+ source->level2ZapTime = cg.time;
+}
+
+/*
==============
CG_EntityEvent
@@ -619,13 +695,13 @@ void CG_EntityEvent( centity_t *cent, vec3_t position )
trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.alienL1Grab );
break;
- case EV_LEV4_CHARGE_PREPARE:
- DEBUGNAME( "EV_LEV4_CHARGE_PREPARE" );
+ case EV_LEV4_TRAMPLE_PREPARE:
+ DEBUGNAME( "EV_LEV4_TRAMPLE_PREPARE" );
trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.alienL4ChargePrepare );
break;
- case EV_LEV4_CHARGE_START:
- DEBUGNAME( "EV_LEV4_CHARGE_START" );
+ case EV_LEV4_TRAMPLE_START:
+ DEBUGNAME( "EV_LEV4_TRAMPLE_START" );
//FIXME: stop cgs.media.alienL4ChargePrepare playing here
trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.alienL4ChargeStart );
break;
@@ -903,6 +979,11 @@ void CG_EntityEvent( centity_t *cent, vec3_t position )
}
break;
+ case EV_MGTURRET_SPINUP:
+ DEBUGNAME( "EV_MGTURRET_SPINUP" );
+ trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.turretSpinupSound );
+ break;
+
case EV_OVERMIND_SPAWNS:
DEBUGNAME( "EV_OVERMIND_SPAWNS" );
if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_ALIENS )
@@ -968,6 +1049,11 @@ void CG_EntityEvent( centity_t *cent, vec3_t position )
cg.spawnTime = cg.time;
break;
+ case EV_LEV2_ZAP:
+ DEBUGNAME( "EV_LEV2_ZAP" );
+ CG_Level2Zap( es );
+ break;
+
default:
DEBUGNAME( "UNKNOWN" );
CG_Error( "Unknown event: %i", event );
diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h
index f70afc85..50381ff2 100644
--- a/src/cgame/cg_local.h
+++ b/src/cgame/cg_local.h
@@ -655,6 +655,7 @@ typedef struct centity_s
qboolean entityPSMissing;
trailSystem_t *level2ZapTS[ 3 ];
+ int level2ZapTime;
trailSystem_t *muzzleTS; //used for the tesla and reactor
int muzzleTSDeathTime;
@@ -1177,6 +1178,7 @@ typedef struct
sfxHandle_t humanTalkSound;
sfxHandle_t landSound;
sfxHandle_t fallSound;
+ sfxHandle_t turretSpinupSound;
sfxHandle_t hardBounceSound1;
sfxHandle_t hardBounceSound2;
@@ -1408,6 +1410,7 @@ extern vmCvar_t cg_drawTeamOverlay;
extern vmCvar_t cg_teamOverlayUserinfo;
extern vmCvar_t cg_crosshairX;
extern vmCvar_t cg_crosshairY;
+extern vmCvar_t cg_crosshairSize;
extern vmCvar_t cg_drawStatus;
extern vmCvar_t cg_draw2D;
extern vmCvar_t cg_animSpeed;
diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c
index bbaf914f..01234d1d 100644
--- a/src/cgame/cg_main.c
+++ b/src/cgame/cg_main.c
@@ -68,6 +68,12 @@ intptr_t vmMain( int command, int arg0, int arg1, int arg2, int arg3,
CG_DrawActiveFrame( arg0, arg1, arg2 );
return 0;
+ case CG_CROSSHAIR_PLAYER:
+ return CG_CrosshairPlayer( );
+
+ case CG_LAST_ATTACKER:
+ return CG_LastAttacker( );
+
case CG_KEY_EVENT:
CG_KeyEvent( arg0, arg1 );
return 0;
@@ -124,6 +130,7 @@ vmCvar_t cg_drawCrosshairNames;
vmCvar_t cg_drawRewards;
vmCvar_t cg_crosshairX;
vmCvar_t cg_crosshairY;
+vmCvar_t cg_crosshairSize;
vmCvar_t cg_draw2D;
vmCvar_t cg_drawStatus;
vmCvar_t cg_animSpeed;
@@ -263,6 +270,7 @@ static cvarTable_t cvarTable[ ] =
{ &cg_drawRewards, "cg_drawRewards", "1", CVAR_ARCHIVE },
{ &cg_crosshairX, "cg_crosshairX", "0", CVAR_ARCHIVE },
{ &cg_crosshairY, "cg_crosshairY", "0", CVAR_ARCHIVE },
+ { &cg_crosshairSize, "cg_crosshairSize", "1", CVAR_ARCHIVE },
{ &cg_brassTime, "cg_brassTime", "2500", CVAR_ARCHIVE },
{ &cg_simpleItems, "cg_simpleItems", "0", CVAR_ARCHIVE },
{ &cg_addMarks, "cg_marks", "1", CVAR_ARCHIVE },
@@ -667,6 +675,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.talkSound = trap_S_RegisterSound( "sound/misc/talk.wav", qfalse );
cgs.media.alienTalkSound = trap_S_RegisterSound( "sound/misc/alien_talk.wav", qfalse );
diff --git a/src/cgame/cg_public.h b/src/cgame/cg_public.h
index 905b1db2..4d9e965a 100644
--- a/src/cgame/cg_public.h
+++ b/src/cgame/cg_public.h
@@ -232,6 +232,12 @@ typedef enum
// Generates and draws a game scene and status information at the given time.
// If demoPlayback is set, local movement prediction will not be enabled
+ CG_CROSSHAIR_PLAYER,
+ // int (*CG_CrosshairPlayer)( void );
+
+ CG_LAST_ATTACKER,
+ // int (*CG_LastAttacker)( void );
+
CG_KEY_EVENT,
// void (*CG_KeyEvent)( int key, qboolean down );
diff --git a/src/cgame/cg_tutorial.c b/src/cgame/cg_tutorial.c
index 21242a75..bfcd03ac 100644
--- a/src/cgame/cg_tutorial.c
+++ b/src/cgame/cg_tutorial.c
@@ -36,6 +36,7 @@ static bind_t bindings[ ] =
{ "+button2", "Activate Upgrade", { -1, -1 } },
{ "+speed", "Run/Walk", { -1, -1 } },
{ "boost", "Sprint", { -1, -1 } },
+ { "+button6", "Dodge", { -1, -1 } },
{ "+moveup", "Jump", { -1, -1 } },
{ "+movedown", "Crouch", { -1, -1 } },
{ "+attack", "Primary Attack", { -1, -1 } },
@@ -340,7 +341,7 @@ static void CG_AlienLevel4Text( char *text, playerState_t *ps )
CG_KeyNameForCommand( "+attack" ) ) );
Q_strcat( text, MAX_TUTORIAL_TEXT,
- va( "Hold down and release %s to charge\n",
+ va( "Hold down and release %s to trample\n",
CG_KeyNameForCommand( "+button5" ) ) );
}
@@ -552,14 +553,25 @@ CG_SpectatorText
*/
static void CG_SpectatorText( char *text, playerState_t *ps )
{
+ if( cgs.clientinfo[ cg.clientNum ].team != PTE_NONE )
+ {
+ Q_strcat( text, MAX_TUTORIAL_TEXT,
+ va( "Press %s to spawn\n",
+ CG_KeyNameForCommand( "+attack" ) ) );
+ }
+ else
+ {
+ Q_strcat( text, MAX_TUTORIAL_TEXT,
+ va( "Press %s to join a team\n",
+ CG_KeyNameForCommand( "+attack" ) ) );
+ }
+
if( ps->pm_flags & PMF_FOLLOW )
{
Q_strcat( text, MAX_TUTORIAL_TEXT,
- va( "Press %s to return to free spectator mode\n",
+ va( "Press %s to stop following\n",
CG_KeyNameForCommand( "+button2" ) ) );
- if( CG_PlayerCount( ) > 1 )
- {
Q_strcat( text, MAX_TUTORIAL_TEXT,
va( "Press %s or ",
CG_KeyNameForCommand( "weapprev" ) ) );
@@ -567,27 +579,13 @@ static void CG_SpectatorText( char *text, playerState_t *ps )
va( "%s to change player\n",
CG_KeyNameForCommand( "weapnext" ) ) );
}
- }
- else if( ps->pm_type == PM_SPECTATOR )
+ else
{
Q_strcat( text, MAX_TUTORIAL_TEXT,
- va( "Press %s to join a team\n",
- CG_KeyNameForCommand( "+attack" ) ) );
-
- if( CG_PlayerCount( ) > 0 )
- {
- Q_strcat( text, MAX_TUTORIAL_TEXT,
- va( "Press %s to enter spectator follow mode\n",
+ va( "Press %s to follow a player\n",
CG_KeyNameForCommand( "+button2" ) ) );
}
}
- else
- {
- Q_strcat( text, MAX_TUTORIAL_TEXT,
- va( "Press %s to spawn\n",
- CG_KeyNameForCommand( "+attack" ) ) );
- }
-}
/*
===============
diff --git a/src/cgame/cg_view.c b/src/cgame/cg_view.c
index 781e068a..ae7cf7bb 100644
--- a/src/cgame/cg_view.c
+++ b/src/cgame/cg_view.c
@@ -470,7 +470,8 @@ static void CG_OffsetFirstPersonView( void )
{
if( ps->stats[ STAT_MISC ] > 0 )
{
- float fraction = (float)ps->stats[ STAT_MISC ] / (float)LEVEL4_CHARGE_TIME;
+ float fraction = (float)ps->stats[ STAT_MISC ] /
+ (float)LEVEL4_TRAMPLE_CHARGE_MAX;
if( fraction > 1.0f )
fraction = 1.0f;
@@ -593,17 +594,17 @@ static void CG_OffsetFirstPersonView( void )
}
// this *feels* more realisitic for humans
- if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_HUMANS )
+ if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_HUMANS &&
+ ( cg.predictedPlayerState.pm_type == PM_NORMAL ||
+ cg.predictedPlayerState.pm_type == PM_JETPACK ) )
{
angles[PITCH] += cg.bobfracsin * bob2 * 0.5;
// heavy breathing effects //FIXME: sound
- if( cg.predictedPlayerState.stats[ STAT_STAMINA ] < 0 )
+ if( cg.predictedPlayerState.stats[ STAT_STAMINA ] < STAMINA_BREATHING_LEVEL )
{
- float deltaBreath = (float)(
- cg.predictedPlayerState.stats[ STAT_STAMINA ] < 0 ?
- -cg.predictedPlayerState.stats[ STAT_STAMINA ] :
- cg.predictedPlayerState.stats[ STAT_STAMINA ] ) / 200.0;
+ float deltaBreath = ( cg.predictedPlayerState.stats[ STAT_STAMINA ] -
+ STAMINA_BREATHING_LEVEL ) / -250.0;
float deltaAngle = cos( (float)cg.time/150.0 ) * deltaBreath;
deltaAngle += ( deltaAngle < 0 ? -deltaAngle : deltaAngle ) * 0.5;
@@ -1067,6 +1068,10 @@ static int CG_CalcViewValues( void )
cg.xyspeed = sqrt( ps->velocity[ 0 ] * ps->velocity[ 0 ] +
ps->velocity[ 1 ] * ps->velocity[ 1 ] );
+ // the bob velocity should't get too fast to avoid jerking
+ if( cg.xyspeed > 300.f )
+ cg.xyspeed = 300.f;
+
VectorCopy( ps->origin, cg.refdef.vieworg );
if( BG_ClassHasAbility( ps->stats[ STAT_PCLASS ], SCA_WALLCLIMBER ) )
diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c
index fc8dc058..a74a15f4 100644
--- a/src/cgame/cg_weapons.c
+++ b/src/cgame/cg_weapons.c
@@ -1061,12 +1061,27 @@ 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 && ps->stats[ STAT_MISC ] > 0 )
+ if( weapon == WP_LUCIFER_CANNON )
{
- float fraction = (float)ps->stats[ STAT_MISC ] / (float)LCANNON_TOTAL_CHARGE;
+ float fraction;
- VectorMA( hand.origin, random( ) * fraction, cg.refdef.viewaxis[ 0 ], hand.origin );
- VectorMA( hand.origin, random( ) * fraction, cg.refdef.viewaxis[ 1 ], hand.origin );
+ 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 );
+ }
}
AnglesToAxis( angles, hand.axis );