summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Angus <tim@ngus.net>2009-10-03 11:37:35 +0000
committerTim Angus <tim@ngus.net>2013-01-03 00:15:11 +0000
commitbac576514472b4f1d70a53078182d29e93c34d59 (patch)
treeacb6f0056003701d26d9d1ed3fb48bb195187be3
parentbcc79996c4c254a528e7b00f260d8ebd09e2a820 (diff)
* First person weapon animation
-rw-r--r--src/cgame/cg_animation.c4
-rw-r--r--src/cgame/cg_animmapobj.c4
-rw-r--r--src/cgame/cg_buildable.c78
-rw-r--r--src/cgame/cg_local.h7
-rw-r--r--src/cgame/cg_particles.c2
-rw-r--r--src/cgame/cg_players.c81
-rw-r--r--src/cgame/cg_weapons.c164
-rw-r--r--src/game/bg_misc.c29
-rw-r--r--src/game/bg_pmove.c74
-rw-r--r--src/game/bg_public.h26
-rw-r--r--src/qcommon/msg.c2
-rw-r--r--src/qcommon/q_shared.h3
12 files changed, 278 insertions, 196 deletions
diff --git a/src/cgame/cg_animation.c b/src/cgame/cg_animation.c
index c370c534..693cf6a7 100644
--- a/src/cgame/cg_animation.c
+++ b/src/cgame/cg_animation.c
@@ -31,7 +31,7 @@ Sets cg.snap, cg.oldFrame, and cg.backlerp
cg.time should be between oldFrameTime and frameTime after exit
===============
*/
-void CG_RunLerpFrame( lerpFrame_t *lf )
+void CG_RunLerpFrame( lerpFrame_t *lf, float scale )
{
int f, numFrames;
animation_t *anim;
@@ -61,7 +61,9 @@ void CG_RunLerpFrame( lerpFrame_t *lf )
lf->frameTime = lf->oldFrameTime + anim->frameLerp;
f = ( lf->frameTime - lf->animationTime ) / anim->frameLerp;
+ f *= scale;
numFrames = anim->numFrames;
+
if( anim->flipflop )
numFrames *= 2;
diff --git a/src/cgame/cg_animmapobj.c b/src/cgame/cg_animmapobj.c
index 12253149..ae2309dd 100644
--- a/src/cgame/cg_animmapobj.c
+++ b/src/cgame/cg_animmapobj.c
@@ -31,7 +31,7 @@ CG_DoorAnimation
*/
static void CG_DoorAnimation( centity_t *cent, int *old, int *now, float *backLerp )
{
- CG_RunLerpFrame( &cent->lerpFrame );
+ CG_RunLerpFrame( &cent->lerpFrame, 1.0f );
*old = cent->lerpFrame.oldFrame;
*now = cent->lerpFrame.frame;
@@ -117,7 +117,7 @@ static void CG_AMOAnimation( centity_t *cent, int *old, int *now, float *backLer
cent->lerpFrame.frameTime += delta;
}
- CG_RunLerpFrame( &cent->lerpFrame );
+ CG_RunLerpFrame( &cent->lerpFrame, 1.0f );
cent->miscTime = cg.time;
}
diff --git a/src/cgame/cg_buildable.c b/src/cgame/cg_buildable.c
index 45f1e8dd..7b20b8b8 100644
--- a/src/cgame/cg_buildable.c
+++ b/src/cgame/cg_buildable.c
@@ -427,19 +427,10 @@ cg.time should be between oldFrameTime and frameTime after exit
*/
static void CG_RunBuildableLerpFrame( centity_t *cent )
{
- int f, numFrames;
buildable_t buildable = cent->currentState.modelindex;
lerpFrame_t *lf = &cent->lerpFrame;
- animation_t *anim;
buildableAnimNumber_t newAnimation = cent->buildableAnim & ~( ANIM_TOGGLEBIT|ANIM_FORCEBIT );
- // debugging tool to get no animations
- if( cg_animSpeed.integer == 0 )
- {
- lf->oldFrame = lf->frame = lf->backlerp = 0;
- return;
- }
-
// see if the animation sequence is switching
if( newAnimation != lf->animationNumber || !lf->animation )
{
@@ -466,72 +457,11 @@ static void CG_RunBuildableLerpFrame( centity_t *cent )
trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin,
cg_buildables[ buildable ].sounds[ lf->animationNumber ].sound );
- // if we have passed the current frame, move it to
- // oldFrame and calculate a new frame
- if( cg.time >= lf->frameTime )
- {
- lf->oldFrame = lf->frame;
- lf->oldFrameTime = lf->frameTime;
-
- // get the next frame based on the animation
- anim = lf->animation;
- if( !anim->frameLerp )
- return; // shouldn't happen
-
- if ( cg.time < lf->animationTime )
- lf->frameTime = lf->animationTime; // initial lerp
- else
- lf->frameTime = lf->oldFrameTime + anim->frameLerp;
-
- f = ( lf->frameTime - lf->animationTime ) / anim->frameLerp;
- numFrames = anim->numFrames;
- if(anim->flipflop)
- numFrames *= 2;
+ CG_RunLerpFrame( lf, 1.0f );
- if( f >= numFrames )
- {
- f -= numFrames;
- if( anim->loopFrames )
- {
- f %= anim->loopFrames;
- f += anim->numFrames - anim->loopFrames;
- }
- else
- {
- f = numFrames - 1;
- // the animation is stuck at the end, so it
- // can immediately transition to another sequence
- lf->frameTime = cg.time;
- cent->buildableAnim = cent->currentState.torsoAnim;
- }
- }
-
- if( anim->reversed )
- lf->frame = anim->firstFrame + anim->numFrames - 1 - f;
- else if( anim->flipflop && f >= anim->numFrames )
- lf->frame = anim->firstFrame + anim->numFrames - 1 - ( f % anim->numFrames );
- else
- lf->frame = anim->firstFrame + f;
-
- if( cg.time > lf->frameTime )
- {
- lf->frameTime = cg.time;
- if( cg_debugAnim.integer )
- CG_Printf( "Clamp lf->frameTime\n");
- }
- }
-
- if( lf->frameTime > cg.time + 200 )
- lf->frameTime = cg.time;
-
- if( lf->oldFrameTime > cg.time )
- lf->oldFrameTime = cg.time;
-
- // calculate current lerp value
- if( lf->frameTime == lf->oldFrameTime )
- lf->backlerp = 0;
- else
- lf->backlerp = 1.0 - (float)( cg.time - lf->oldFrameTime ) / ( lf->frameTime - lf->oldFrameTime );
+ // animation ended
+ if( lf->frameTime == cg.time )
+ cent->buildableAnim = cent->currentState.torsoAnim;
}
/*
diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h
index 4b375d43..470069c1 100644
--- a/src/cgame/cg_local.h
+++ b/src/cgame/cg_local.h
@@ -569,7 +569,7 @@ typedef struct
typedef struct
{
- lerpFrame_t legs, torso, flag, nonseg;
+ lerpFrame_t legs, torso, nonseg, weapon;
int painTime;
int painDirection; // flip from 0 to 1
@@ -825,6 +825,9 @@ typedef struct weaponInfo_s
qhandle_t barrelModel;
qhandle_t flashModel;
+ animation_t animations[ MAX_WEAPON_ANIMATIONS ];
+ qboolean noDrift;
+
vec3_t weaponMidpoint; // so it will rotate centered instead of by tag
qhandle_t weaponIcon;
@@ -1669,7 +1672,7 @@ void CG_AlienBuildableExplosion( vec3_t origin, vec3_t dir );
//
// cg_animation.c
//
-void CG_RunLerpFrame( lerpFrame_t *lf );
+void CG_RunLerpFrame( lerpFrame_t *lf, float scale );
//
// cg_animmapobj.c
diff --git a/src/cgame/cg_particles.c b/src/cgame/cg_particles.c
index 195c5ff3..c7023dbf 100644
--- a/src/cgame/cg_particles.c
+++ b/src/cgame/cg_particles.c
@@ -2416,7 +2416,7 @@ static void CG_RenderParticle( particle_t *p )
p->lf.animation = &bp->modelAnimation;
//run animation
- CG_RunLerpFrame( &p->lf );
+ CG_RunLerpFrame( &p->lf, 1.0f );
re.oldframe = p->lf.oldFrame;
re.frame = p->lf.frame;
diff --git a/src/cgame/cg_players.c b/src/cgame/cg_players.c
index 78cbe8d8..f729164a 100644
--- a/src/cgame/cg_players.c
+++ b/src/cgame/cg_players.c
@@ -841,90 +841,11 @@ cg.time should be between oldFrameTime and frameTime after exit
*/
static void CG_RunPlayerLerpFrame( clientInfo_t *ci, lerpFrame_t *lf, int newAnimation, float speedScale )
{
- int f, numFrames;
- animation_t *anim;
-
- // debugging tool to get no animations
- if( cg_animSpeed.integer == 0 )
- {
- lf->oldFrame = lf->frame = lf->backlerp = 0;
- return;
- }
-
// see if the animation sequence is switching
if( newAnimation != lf->animationNumber || !lf->animation )
- {
CG_SetLerpFrameAnimation( ci, lf, newAnimation );
- }
- // if we have passed the current frame, move it to
- // oldFrame and calculate a new frame
- if( cg.time >= lf->frameTime )
- {
- lf->oldFrame = lf->frame;
- lf->oldFrameTime = lf->frameTime;
-
- // get the next frame based on the animation
- anim = lf->animation;
- if( !anim->frameLerp )
- return; // shouldn't happen
-
- if( cg.time < lf->animationTime )
- lf->frameTime = lf->animationTime; // initial lerp
- else
- lf->frameTime = lf->oldFrameTime + anim->frameLerp;
-
- f = ( lf->frameTime - lf->animationTime ) / anim->frameLerp;
- f *= speedScale; // adjust for haste, etc
- numFrames = anim->numFrames;
-
- if( anim->flipflop )
- numFrames *= 2;
-
- if( f >= numFrames )
- {
- f -= numFrames;
- if( anim->loopFrames )
- {
- f %= anim->loopFrames;
- f += anim->numFrames - anim->loopFrames;
- }
- else
- {
- f = numFrames - 1;
- // the animation is stuck at the end, so it
- // can immediately transition to another sequence
- lf->frameTime = cg.time;
- }
- }
-
- if( anim->reversed )
- lf->frame = anim->firstFrame + anim->numFrames - 1 - f;
- else if( anim->flipflop && f>=anim->numFrames )
- lf->frame = anim->firstFrame + anim->numFrames - 1 - ( f % anim->numFrames );
- else
- lf->frame = anim->firstFrame + f;
-
- if( cg.time > lf->frameTime )
- {
- lf->frameTime = cg.time;
-
- if( cg_debugAnim.integer )
- CG_Printf( "Clamp lf->frameTime\n" );
- }
- }
-
- if( lf->frameTime > cg.time + 200 )
- lf->frameTime = cg.time;
-
- if( lf->oldFrameTime > cg.time )
- lf->oldFrameTime = cg.time;
-
- // calculate current lerp value
- if( lf->frameTime == lf->oldFrameTime )
- lf->backlerp = 0;
- else
- lf->backlerp = 1.0 - (float)( cg.time - lf->oldFrameTime ) / ( lf->frameTime - lf->oldFrameTime );
+ CG_RunLerpFrame( lf, speedScale );
}
diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c
index e3776779..f9ea2985 100644
--- a/src/cgame/cg_weapons.c
+++ b/src/cgame/cg_weapons.c
@@ -80,6 +80,104 @@ void CG_InitUpgrades( void )
/*
+======================
+CG_ParseWeaponAnimationFile
+
+Read a configuration file containing animation counts and rates
+models/weapons/rifle/animation.cfg, etc
+======================
+*/
+static qboolean CG_ParseWeaponAnimationFile( const char *filename, weaponInfo_t *weapon )
+{
+ char *text_p;
+ int len;
+ int i;
+ char *token;
+ float fps;
+ char text[ 20000 ];
+ fileHandle_t f;
+ animation_t *animations;
+
+ animations = weapon->animations;
+
+ // load the file
+ len = trap_FS_FOpenFile( filename, &f, FS_READ );
+ if( len <= 0 )
+ return qfalse;
+
+ if( len >= sizeof( text ) - 1 )
+ {
+ CG_Printf( "File %s too long\n", filename );
+ return qfalse;
+ }
+
+ trap_FS_Read( text, len, f );
+ text[ len ] = 0;
+ trap_FS_FCloseFile( f );
+
+ // parse the text
+ text_p = text;
+
+ // read information for each frame
+ for( i = WANIM_NONE + 1; i < MAX_WEAPON_ANIMATIONS; i++ )
+ {
+
+ token = COM_Parse( &text_p );
+ if( !*token )
+ break;
+
+ if( !Q_stricmp( token, "noDrift" ) )
+ {
+ weapon->noDrift = qtrue;
+ continue;
+ }
+
+ animations[ i ].firstFrame = atoi( token );
+
+ token = COM_Parse( &text_p );
+ if( !*token )
+ break;
+
+ animations[ i ].numFrames = atoi( token );
+ animations[ i ].reversed = qfalse;
+ animations[ i ].flipflop = qfalse;
+
+ // if numFrames is negative the animation is reversed
+ if( animations[ i ].numFrames < 0 )
+ {
+ animations[ i ].numFrames = -animations[ i ].numFrames;
+ animations[ i ].reversed = qtrue;
+ }
+
+ token = COM_Parse( &text_p );
+ if ( !*token )
+ break;
+
+ animations[i].loopFrames = atoi( token );
+
+ token = COM_Parse( &text_p );
+ if( !*token )
+ break;
+
+ fps = atof( token );
+ if( fps == 0 )
+ fps = 1;
+
+ animations[ i ].frameLerp = 1000 / fps;
+ animations[ i ].initialLerp = 1000 / fps;
+ }
+
+ if( i != MAX_WEAPON_ANIMATIONS )
+ {
+ CG_Printf( "Error parsing animation file: %s\n", filename );
+ return qfalse;
+ }
+
+ return qtrue;
+}
+
+
+/*
===============
CG_ParseWeaponModeSection
@@ -627,6 +725,11 @@ void CG_RegisterWeapon( int weaponNum )
if( !CG_ParseWeaponFile( path, weaponInfo ) )
Com_Printf( S_COLOR_RED "ERROR: failed to parse %s\n", path );
+ Com_sprintf( path, MAX_QPATH, "models/weapons/%s/animation.cfg", BG_FindNameForWeapon( weaponNum ) );
+
+ if( !CG_ParseWeaponAnimationFile( path, weaponInfo ) )
+ Com_Printf( S_COLOR_RED "ERROR: failed to parse %s\n", path );
+
// calc midpoint for rotation
trap_R_ModelBounds( weaponInfo->weaponModel, mins, maxs );
for( i = 0 ; i < 3 ; i++ )
@@ -666,6 +769,53 @@ VIEW WEAPON
*/
/*
+===============
+CG_SetWeaponLerpFrameAnimation
+
+may include ANIM_TOGGLEBIT
+===============
+*/
+static void CG_SetWeaponLerpFrameAnimation( weapon_t weapon, lerpFrame_t *lf, int newAnimation )
+{
+ animation_t *anim;
+
+ lf->animationNumber = newAnimation;
+ newAnimation &= ~ANIM_TOGGLEBIT;
+
+ if( newAnimation < 0 || newAnimation >= MAX_WEAPON_ANIMATIONS )
+ CG_Error( "Bad animation number: %i", newAnimation );
+
+ anim = &cg_weapons[ weapon ].animations[ newAnimation ];
+
+ lf->animation = anim;
+ lf->animationTime = lf->frameTime + anim->initialLerp;
+
+ if( cg_debugAnim.integer )
+ CG_Printf( "Anim: %i\n", newAnimation );
+}
+
+/*
+===============
+CG_WeaponAnimation
+===============
+*/
+static void CG_WeaponAnimation( centity_t *cent, int *old, int *now, float *backLerp )
+{
+ lerpFrame_t *lf = &cent->pe.weapon;
+ entityState_t *es = &cent->currentState;
+
+ // see if the animation sequence is switching
+ if( es->weaponAnim != lf->animationNumber || !lf->animation )
+ CG_SetWeaponLerpFrameAnimation( es->weapon, lf, es->weaponAnim );
+
+ CG_RunLerpFrame( lf, 1.0f );
+
+ *old = lf->oldFrame;
+ *now = lf->frame;
+ *backLerp = lf->backlerp;
+}
+
+/*
=================
CG_MapTorsoToWeaponFrame
@@ -700,10 +850,13 @@ CG_CalculateWeaponPosition
*/
static void CG_CalculateWeaponPosition( vec3_t origin, vec3_t angles )
{
- float scale;
- int delta;
- float fracsin;
- float bob;
+ float scale;
+ int delta;
+ float fracsin;
+ float bob;
+ weaponInfo_t *weapon;
+
+ weapon = &cg_weapons[ cg.predictedPlayerState.weapon ];
VectorCopy( cg.refdef.vieworg, origin );
VectorCopy( cg.refdefViewAngles, angles );
@@ -726,7 +879,7 @@ static void CG_CalculateWeaponPosition( vec3_t origin, vec3_t angles )
}
// drop the weapon when landing
- if( !BG_ClassHasAbility( cg.predictedPlayerState.stats[ STAT_PCLASS ], SCA_NOWEAPONDRIFT ) )
+ if( weapon->noDrift )
{
delta = cg.time - cg.landTime;
if( delta < LAND_DEFLECT_TIME )
@@ -880,6 +1033,7 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
if( !noGunModel )
{
+ CG_WeaponAnimation( cent, &gun.oldframe, &gun.frame, &gun.backlerp );
CG_PositionEntityOnTag( &gun, parent, parent->hModel, "tag_weapon" );
trap_R_AddRefEntityToScene( &gun );
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c
index 275f5b41..64924aaa 100644
--- a/src/game/bg_misc.c
+++ b/src/game/bg_misc.c
@@ -1735,8 +1735,7 @@ classAttributes_t bg_classList[ ] =
LEVEL0_HEALTH, //int health;
0.0f, //float fallDamage;
LEVEL0_REGEN, //int regenRate;
- SCA_WALLCLIMBER|SCA_NOWEAPONDRIFT|
- SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
+ SCA_WALLCLIMBER|SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
WP_ALEVEL0, //weapon_t startWeapon
0.0f, //float buildDist;
140, //int fov;
@@ -1778,8 +1777,7 @@ classAttributes_t bg_classList[ ] =
LEVEL1_HEALTH, //int health;
0.0f, //float fallDamage;
LEVEL1_REGEN, //int regenRate;
- SCA_NOWEAPONDRIFT|
- SCA_FOVWARPS|SCA_WALLCLIMBER|SCA_ALIENSENSE, //int abilities;
+ SCA_FOVWARPS|SCA_WALLCLIMBER|SCA_ALIENSENSE, //int abilities;
WP_ALEVEL1, //weapon_t startWeapon
0.0f, //float buildDist;
120, //int fov;
@@ -1821,8 +1819,7 @@ classAttributes_t bg_classList[ ] =
LEVEL1_UPG_HEALTH, //int health;
0.0f, //float fallDamage;
LEVEL1_UPG_REGEN, //int regenRate;
- SCA_NOWEAPONDRIFT|SCA_FOVWARPS|
- SCA_WALLCLIMBER|SCA_ALIENSENSE, //int abilities;
+ SCA_FOVWARPS|SCA_WALLCLIMBER|SCA_ALIENSENSE, //int abilities;
WP_ALEVEL1_UPG, //weapon_t startWeapon
0.0f, //float buildDist;
120, //int fov;
@@ -1862,8 +1859,7 @@ classAttributes_t bg_classList[ ] =
LEVEL2_HEALTH, //int health;
0.0f, //float fallDamage;
LEVEL2_REGEN, //int regenRate;
- SCA_NOWEAPONDRIFT|SCA_WALLJUMPER|
- SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
+ SCA_WALLJUMPER|SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
WP_ALEVEL2, //weapon_t startWeapon
0.0f, //float buildDist;
90, //int fov;
@@ -1903,8 +1899,7 @@ classAttributes_t bg_classList[ ] =
LEVEL2_UPG_HEALTH, //int health;
0.0f, //float fallDamage;
LEVEL2_UPG_REGEN, //int regenRate;
- SCA_NOWEAPONDRIFT|SCA_WALLJUMPER|
- SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
+ SCA_WALLJUMPER|SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
WP_ALEVEL2_UPG, //weapon_t startWeapon
0.0f, //float buildDist;
90, //int fov;
@@ -1945,8 +1940,7 @@ classAttributes_t bg_classList[ ] =
LEVEL3_HEALTH, //int health;
0.0f, //float fallDamage;
LEVEL3_REGEN, //int regenRate;
- SCA_NOWEAPONDRIFT|
- SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
+ SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
WP_ALEVEL3, //weapon_t startWeapon
0.0f, //float buildDist;
110, //int fov;
@@ -1987,8 +1981,7 @@ classAttributes_t bg_classList[ ] =
LEVEL3_UPG_HEALTH, //int health;
0.0f, //float fallDamage;
LEVEL3_UPG_REGEN, //int regenRate;
- SCA_NOWEAPONDRIFT|
- SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
+ SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
WP_ALEVEL3_UPG, //weapon_t startWeapon
0.0f, //float buildDist;
110, //int fov;
@@ -2030,8 +2023,7 @@ classAttributes_t bg_classList[ ] =
LEVEL4_HEALTH, //int health;
0.0f, //float fallDamage;
LEVEL4_REGEN, //int regenRate;
- SCA_NOWEAPONDRIFT|
- SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
+ SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
WP_ALEVEL4, //weapon_t startWeapon
0.0f, //float buildDist;
90, //int fov;
@@ -2070,8 +2062,7 @@ classAttributes_t bg_classList[ ] =
100, //int health;
1.0f, //float fallDamage;
0, //int regenRate;
- SCA_TAKESFALLDAMAGE|
- SCA_CANUSELADDERS, //int abilities;
+ SCA_TAKESFALLDAMAGE|SCA_CANUSELADDERS, //int abilities;
WP_NONE, //special-cased in g_client.c //weapon_t startWeapon
110.0f, //float buildDist;
90, //int fov;
@@ -4953,6 +4944,7 @@ void BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean
s->time2 = ps->movementDir;
s->legsAnim = ps->legsAnim;
s->torsoAnim = ps->torsoAnim;
+ s->weaponAnim = ps->weaponAnim;
s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number
// so corpses can also reference the proper config
s->eFlags = ps->eFlags;
@@ -5062,6 +5054,7 @@ void BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *s
s->time2 = ps->movementDir;
s->legsAnim = ps->legsAnim;
s->torsoAnim = ps->torsoAnim;
+ s->weaponAnim = ps->weaponAnim;
s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number
// so corpses can also reference the proper config
s->eFlags = ps->eFlags;
diff --git a/src/game/bg_pmove.c b/src/game/bg_pmove.c
index d0f0a1c6..5179c24c 100644
--- a/src/game/bg_pmove.c
+++ b/src/game/bg_pmove.c
@@ -103,6 +103,20 @@ void PM_StartTorsoAnim( int anim )
/*
===================
+PM_StartWeaponAnim
+===================
+*/
+static void PM_StartWeaponAnim( int anim )
+{
+ if( pm->ps->pm_type >= PM_DEAD )
+ return;
+
+ pm->ps->weaponAnim = ( ( pm->ps->torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT )
+ | anim;
+}
+
+/*
+===================
PM_StartLegsAnim
===================
*/
@@ -170,6 +184,19 @@ static void PM_ContinueTorsoAnim( int anim )
/*
===================
+PM_ContinueWeaponAnim
+===================
+*/
+static void PM_ContinueWeaponAnim( int anim )
+{
+ if( ( pm->ps->weaponAnim & ~ANIM_TOGGLEBIT ) == anim )
+ return;
+
+ PM_StartWeaponAnim( anim );
+}
+
+/*
+===================
PM_ForceLegsAnim
===================
*/
@@ -2716,7 +2743,10 @@ static void PM_BeginWeaponChange( int weapon )
pm->ps->stats[ STAT_BUILDABLE ] = BA_NONE;
if( !( pm->ps->persistant[ PERS_STATE ] & PS_NONSEGMODEL ) )
+ {
PM_StartTorsoAnim( TORSO_DROP );
+ PM_StartWeaponAnim( WANIM_DROP );
+ }
}
@@ -2741,7 +2771,10 @@ static void PM_FinishWeaponChange( void )
pm->ps->weaponTime += 250;
if( !( pm->ps->persistant[ PERS_STATE ] & PS_NONSEGMODEL ) )
+ {
PM_StartTorsoAnim( TORSO_RAISE );
+ PM_StartWeaponAnim( WANIM_RAISE );
+ }
}
@@ -2753,15 +2786,17 @@ PM_TorsoAnimation
*/
static void PM_TorsoAnimation( void )
{
- if( pm->ps->persistant[ PERS_STATE ] & PS_NONSEGMODEL )
- return;
-
if( pm->ps->weaponstate == WEAPON_READY )
{
- if( pm->ps->weapon == WP_BLASTER )
- PM_ContinueTorsoAnim( TORSO_STAND2 );
- else
- PM_ContinueTorsoAnim( TORSO_STAND );
+ if( !( pm->ps->persistant[ PERS_STATE ] & PS_NONSEGMODEL ) )
+ {
+ if( pm->ps->weapon == WP_BLASTER )
+ PM_ContinueTorsoAnim( TORSO_STAND2 );
+ else
+ PM_ContinueTorsoAnim( TORSO_STAND );
+ }
+
+ PM_ContinueWeaponAnim( WANIM_IDLE );
}
}
@@ -2969,6 +3004,8 @@ static void PM_Weapon( void )
PM_ContinueTorsoAnim( TORSO_STAND );
}
+ PM_ContinueWeaponAnim( WANIM_IDLE );
+
return;
}
@@ -3010,7 +3047,6 @@ static void PM_Weapon( void )
//allow some time for the weapon to be raised
pm->ps->weaponstate = WEAPON_RAISING;
- PM_StartTorsoAnim( TORSO_RAISE );
pm->ps->weaponTime += 250;
return;
}
@@ -3023,6 +3059,7 @@ static void PM_Weapon( void )
//drop the weapon
PM_StartTorsoAnim( TORSO_DROP );
+ PM_StartWeaponAnim( WANIM_RELOAD );
pm->ps->weaponTime += BG_FindReloadTimeForWeapon( pm->ps->weapon );
return;
@@ -3207,15 +3244,18 @@ static void PM_Weapon( void )
if( pm->ps->weaponstate == WEAPON_READY )
{
PM_StartTorsoAnim( TORSO_ATTACK );
+ PM_StartWeaponAnim( WANIM_ATTACK1 );
}
break;
case WP_BLASTER:
PM_StartTorsoAnim( TORSO_ATTACK2 );
+ PM_StartWeaponAnim( WANIM_ATTACK1 );
break;
default:
PM_StartTorsoAnim( TORSO_ATTACK );
+ PM_StartWeaponAnim( WANIM_ATTACK1 );
break;
}
}
@@ -3227,20 +3267,38 @@ static void PM_Weapon( void )
int num = abs( pm->ps->commandTime ) % 3;
if( num == 0 )
+ {
PM_ForceLegsAnim( NSPA_ATTACK1 );
+ PM_StartWeaponAnim( WANIM_ATTACK1 );
+ }
else if( num == 1 )
+ {
PM_ForceLegsAnim( NSPA_ATTACK2 );
+ PM_StartWeaponAnim( WANIM_ATTACK2 );
+ }
else if( num == 2 )
+ {
PM_ForceLegsAnim( NSPA_ATTACK3 );
+ PM_StartWeaponAnim( WANIM_ATTACK3 );
+ }
}
else
{
if( attack1 )
+ {
PM_ForceLegsAnim( NSPA_ATTACK1 );
+ PM_StartWeaponAnim( WANIM_ATTACK1 );
+ }
else if( attack2 )
+ {
PM_ForceLegsAnim( NSPA_ATTACK2 );
+ PM_StartWeaponAnim( WANIM_ATTACK2 );
+ }
else if( attack3 )
+ {
PM_ForceLegsAnim( NSPA_ATTACK3 );
+ PM_StartWeaponAnim( WANIM_ATTACK3 );
+ }
}
pm->ps->torsoTimer = TIMER_ATTACK;
diff --git a/src/game/bg_public.h b/src/game/bg_public.h
index 1ee8d36a..361d857a 100644
--- a/src/game/bg_public.h
+++ b/src/game/bg_public.h
@@ -225,11 +225,10 @@ typedef enum
#define SCA_WALLCLIMBER 0x00000001
#define SCA_TAKESFALLDAMAGE 0x00000002
#define SCA_CANZOOM 0x00000004
-#define SCA_NOWEAPONDRIFT 0x00000008
-#define SCA_FOVWARPS 0x00000010
-#define SCA_ALIENSENSE 0x00000020
-#define SCA_CANUSELADDERS 0x00000040
-#define SCA_WALLJUMPER 0x00000080
+#define SCA_FOVWARPS 0x00000008
+#define SCA_ALIENSENSE 0x00000010
+#define SCA_CANUSELADDERS 0x00000020
+#define SCA_WALLJUMPER 0x00000040
#define SS_WALLCLIMBING 0x00000001
#define SS_WALLCLIMBINGCEILING 0x00000002
@@ -770,6 +769,23 @@ typedef enum
MAX_BUILDABLE_ANIMATIONS
} buildableAnimNumber_t;
+typedef enum
+{
+ WANIM_NONE,
+
+ WANIM_IDLE,
+
+ WANIM_DROP,
+ WANIM_RELOAD,
+ WANIM_RAISE,
+
+ WANIM_ATTACK1,
+ WANIM_ATTACK2,
+ WANIM_ATTACK3,
+
+ MAX_WEAPON_ANIMATIONS
+} weaponAnimNumber_t;
+
typedef struct animation_s
{
int firstFrame;
diff --git a/src/qcommon/msg.c b/src/qcommon/msg.c
index ac581b9e..47fbc2dc 100644
--- a/src/qcommon/msg.c
+++ b/src/qcommon/msg.c
@@ -808,6 +808,7 @@ netField_t entityStateFields[] =
{ NETF(angles2[1]), 0 },
{ NETF(eType), 8 },
{ NETF(torsoAnim), 8 },
+{ NETF(weaponAnim), 8 },
{ NETF(eventParm), 8 },
{ NETF(legsAnim), 8 },
{ NETF(groundEntityNum), GENTITYNUM_BITS },
@@ -1125,6 +1126,7 @@ netField_t playerStateFields[] =
{ PSF(pm_time), -16 },
{ PSF(eventSequence), 16 },
{ PSF(torsoAnim), 8 },
+{ PSF(weaponAnim), 8 },
{ PSF(movementDir), 4 },
{ PSF(events[0]), 8 },
{ PSF(legsAnim), 8 },
diff --git a/src/qcommon/q_shared.h b/src/qcommon/q_shared.h
index 667fba73..232982f5 100644
--- a/src/qcommon/q_shared.h
+++ b/src/qcommon/q_shared.h
@@ -1060,6 +1060,8 @@ typedef struct playerState_s {
int torsoTimer; // don't change low priority animations until this runs out
int torsoAnim; // mask off ANIM_TOGGLEBIT
+ int weaponAnim; // mask off ANIM_TOGGLEBIT
+
int movementDir; // a number 0 to 7 that represents the reletive angle
// of movement to the view angle (axial and diagonals)
// when at rest, the value will remain unchanged
@@ -1212,6 +1214,7 @@ typedef struct entityState_s {
int weapon; // determines weapon and flash model, etc
int legsAnim; // mask off ANIM_TOGGLEBIT
int torsoAnim; // mask off ANIM_TOGGLEBIT
+ int weaponAnim; // mask off ANIM_TOGGLEBIT
int generic1;
} entityState_t;