diff options
-rw-r--r-- | src/cgame/cg_local.h | 5 | ||||
-rw-r--r-- | src/cgame/cg_players.c | 333 | ||||
-rw-r--r-- | src/game/bg_misc.c | 4 |
3 files changed, 266 insertions, 76 deletions
diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h index 81a0908a..23bf1867 100644 --- a/src/cgame/cg_local.h +++ b/src/cgame/cg_local.h @@ -149,7 +149,7 @@ typedef struct typedef struct { - lerpFrame_t legs, torso, flag; + lerpFrame_t legs, torso, flag, nonseg; int painTime; int painDirection; // flip from 0 to 1 int lightningFiring; @@ -400,6 +400,9 @@ typedef struct qhandle_t headModel; qhandle_t headSkin; + qhandle_t nonSegModel; //non-segmented model system + qhandle_t nonSegSkin; //non-segmented model system + qhandle_t modelIcon; animation_t animations[ MAX_PLAYER_TOTALANIMATIONS ]; diff --git a/src/cgame/cg_players.c b/src/cgame/cg_players.c index 5384a44e..bfbd039e 100644 --- a/src/cgame/cg_players.c +++ b/src/cgame/cg_players.c @@ -120,6 +120,7 @@ static qboolean CG_ParseAnimationFile( const char *filename, clientInfo_t *ci ) ci->gender = GENDER_MALE; ci->fixedlegs = qfalse; ci->fixedtorso = qfalse; + ci->nonsegmented = qfalse; // read optional parameters while( 1 ) @@ -377,23 +378,36 @@ static qboolean CG_RegisterClientSkin( clientInfo_t *ci, const char *modelName, { char filename[ MAX_QPATH ]; - Com_sprintf( filename, sizeof( filename ), "models/players/%s/lower_%s.skin", modelName, skinName ); - ci->legsSkin = trap_R_RegisterSkin( filename ); - if( !ci->legsSkin ) - Com_Printf( "Leg skin load failure: %s\n", filename ); - - Com_sprintf( filename, sizeof( filename ), "models/players/%s/upper_%s.skin", modelName, skinName ); - ci->torsoSkin = trap_R_RegisterSkin( filename ); - if( !ci->torsoSkin ) - Com_Printf( "Torso skin load failure: %s\n", filename ); - - Com_sprintf( filename, sizeof( filename ), "models/players/%s/head_%s.skin", modelName, skinName ); - ci->headSkin = trap_R_RegisterSkin( filename ); - if( !ci->headSkin ) - Com_Printf( "Head skin load failure: %s\n", filename ); + if( !ci->nonsegmented ) + { + Com_sprintf( filename, sizeof( filename ), "models/players/%s/lower_%s.skin", modelName, skinName ); + ci->legsSkin = trap_R_RegisterSkin( filename ); + if( !ci->legsSkin ) + Com_Printf( "Leg skin load failure: %s\n", filename ); + + Com_sprintf( filename, sizeof( filename ), "models/players/%s/upper_%s.skin", modelName, skinName ); + ci->torsoSkin = trap_R_RegisterSkin( filename ); + if( !ci->torsoSkin ) + Com_Printf( "Torso skin load failure: %s\n", filename ); + + Com_sprintf( filename, sizeof( filename ), "models/players/%s/head_%s.skin", modelName, skinName ); + ci->headSkin = trap_R_RegisterSkin( filename ); + if( !ci->headSkin ) + Com_Printf( "Head skin load failure: %s\n", filename ); + + if( !ci->legsSkin || !ci->torsoSkin || !ci->headSkin ) + return qfalse; + } + else + { + Com_sprintf( filename, sizeof( filename ), "models/players/%s/nonseg_%s.skin", modelName, skinName ); + ci->nonSegSkin = trap_R_RegisterSkin( filename ); + if( !ci->nonSegSkin ) + Com_Printf( "Non-segmented skin load failure: %s\n", filename ); - if( !ci->legsSkin || !ci->torsoSkin || !ci->headSkin ) - return qfalse; + if( !ci->nonSegSkin ) + return qfalse; + } return qtrue; } @@ -407,30 +421,52 @@ static qboolean CG_RegisterClientModelname( clientInfo_t *ci, const char *modelN { char filename[ MAX_QPATH * 2 ]; - // load cmodels before models so filecache works - - Com_sprintf( filename, sizeof( filename ), "models/players/%s/lower.md3", modelName ); - ci->legsModel = trap_R_RegisterModel( filename ); - if( !ci->legsModel ) + //TA: do this first so the nonsegemented property is set + // load the animations + Com_sprintf( filename, sizeof( filename ), "models/players/%s/animation.cfg", modelName ); + if( !CG_ParseAnimationFile( filename, ci ) ) { - Com_Printf( "Failed to load model file %s\n", filename ); + Com_Printf( "Failed to load animation file %s\n", filename ); return qfalse; } - Com_sprintf( filename, sizeof( filename ), "models/players/%s/upper.md3", modelName ); - ci->torsoModel = trap_R_RegisterModel( filename ); - if( !ci->torsoModel ) + // load cmodels before models so filecache works + + if( !ci->nonsegmented ) { - Com_Printf( "Failed to load model file %s\n", filename ); - return qfalse; - } + Com_sprintf( filename, sizeof( filename ), "models/players/%s/lower.md3", modelName ); + ci->legsModel = trap_R_RegisterModel( filename ); + if( !ci->legsModel ) + { + Com_Printf( "Failed to load model file %s\n", filename ); + return qfalse; + } + + Com_sprintf( filename, sizeof( filename ), "models/players/%s/upper.md3", modelName ); + ci->torsoModel = trap_R_RegisterModel( filename ); + if( !ci->torsoModel ) + { + Com_Printf( "Failed to load model file %s\n", filename ); + return qfalse; + } - Com_sprintf( filename, sizeof( filename ), "models/players/%s/head.md3", modelName ); - ci->headModel = trap_R_RegisterModel( filename ); - if( !ci->headModel ) + Com_sprintf( filename, sizeof( filename ), "models/players/%s/head.md3", modelName ); + ci->headModel = trap_R_RegisterModel( filename ); + if( !ci->headModel ) + { + Com_Printf( "Failed to load model file %s\n", filename ); + return qfalse; + } + } + else { - Com_Printf( "Failed to load model file %s\n", filename ); - return qfalse; + Com_sprintf( filename, sizeof( filename ), "models/players/%s/nonseg.md3", modelName ); + ci->nonSegModel = trap_R_RegisterModel( filename ); + if( !ci->nonSegModel ) + { + Com_Printf( "Failed to load model file %s\n", filename ); + return qfalse; + } } // if any skins failed to load, return failure @@ -440,14 +476,6 @@ static qboolean CG_RegisterClientModelname( clientInfo_t *ci, const char *modelN return qfalse; } - // load the animations - Com_sprintf( filename, sizeof( filename ), "models/players/%s/animation.cfg", modelName ); - if( !CG_ParseAnimationFile( filename, ci ) ) - { - Com_Printf( "Failed to load animation file %s\n", filename ); - return qfalse; - } - Com_sprintf( filename, sizeof( filename ), "models/players/%s/icon_%s.tga", modelName, skinName ); ci->modelIcon = trap_R_RegisterShaderNoMip( filename ); if( !ci->modelIcon ) @@ -563,6 +591,8 @@ static void CG_CopyClientInfoModel( clientInfo_t *from, clientInfo_t *to ) to->torsoSkin = from->torsoSkin; to->headModel = from->headModel; to->headSkin = from->headSkin; + to->nonSegModel = from->nonSegModel; + to->nonSegSkin = from->nonSegSkin; to->modelIcon = from->modelIcon; memcpy( to->animations, from->animations, sizeof( to->animations ) ); @@ -1154,6 +1184,40 @@ static void CG_PlayerAnimation( centity_t *cent, int *legsOld, int *legs, float *torsoBackLerp = cent->pe.torso.backlerp; } + +/* +=============== +CG_PlayerNonSegAnimation +=============== +*/ +static void CG_PlayerNonSegAnimation( centity_t *cent, int *nonSegOld, + int *nonSeg, float *nonSegBackLerp ) +{ + clientInfo_t *ci; + int clientNum; + float speedScale = 1.0f; + + clientNum = cent->currentState.clientNum; + + if( cg_noPlayerAnims.integer ) + { + *nonSegOld = *nonSeg = 0; + return; + } + + ci = &cgs.clientinfo[ clientNum ]; + + // do the shuffle turn frames locally + if( cent->pe.nonseg.yawing && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == NSPA_STAND ) + CG_RunLerpFrame( ci, ¢->pe.nonseg, NSPA_TURN, speedScale ); + else + CG_RunLerpFrame( ci, ¢->pe.legs, cent->currentState.legsAnim, speedScale ); + + *nonSegOld = cent->pe.nonseg.oldFrame; + *nonSeg = cent->pe.nonseg.frame; + *nonSegBackLerp = cent->pe.nonseg.backlerp; +} + /* ============================================================================= @@ -1402,6 +1466,101 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t srcAngles, } +/* +=============== +CG_PlayerNonSegAngles + +Resolve angles for non-segmented models +=============== +*/ +static void CG_PlayerNonSegAngles( centity_t *cent, vec3_t srcAngles, vec3_t nonSegAxis[ 3 ] ) +{ + vec3_t localAngles; + float dest; + static int movementOffsets[ 8 ] = { 0, 22, 45, -22, 0, 22, -45, -22 }; + vec3_t velocity; + float speed; + int dir, clientNum; + clientInfo_t *ci; + + VectorCopy( srcAngles, localAngles ); + localAngles[ YAW ] = AngleMod( localAngles[ YAW ] ); + localAngles[ PITCH ] = 0.0f; + localAngles[ ROLL ] = 0.0f; + + // --------- yaw ------------- + + // allow yaw to drift a bit + if( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != NSPA_STAND ) + { + // if not standing still, always point all in the same direction + cent->pe.nonseg.yawing = qtrue; // always center + } + + // adjust legs for movement dir + if( cent->currentState.eFlags & EF_DEAD ) + { + // don't let dead bodies twitch + dir = 0; + } + else + { + //TA: did use angles2.. now uses time2.. looks a bit funny but time2 isn't used othwise + dir = cent->currentState.time2; + if( dir < 0 || dir > 7 ) + CG_Error( "Bad player movement angle" ); + } + + // torso + if( cent->currentState.eFlags & EF_DEAD ) + { + CG_SwingAngles( localAngles[ YAW ], 0, 0, cg_swingSpeed.value, + ¢->pe.nonseg.yawAngle, ¢->pe.nonseg.yawing ); + } + else + { + CG_SwingAngles( localAngles[ YAW ], 40, 90, cg_swingSpeed.value, + ¢->pe.nonseg.yawAngle, ¢->pe.nonseg.yawing ); + } + + localAngles[ YAW ] = cent->pe.nonseg.yawAngle; + + // --------- pitch ------------- + + //NO PITCH! + + + // --------- roll ------------- + + + // lean towards the direction of travel + VectorCopy( cent->currentState.pos.trDelta, velocity ); + speed = VectorNormalize( velocity ); + + if( speed ) + { + vec3_t axis[ 3 ]; + float side; + + //much less than with the regular model system + speed *= 0.01f; + + AnglesToAxis( localAngles, axis ); + side = speed * DotProduct( velocity, axis[ 1 ] ); + localAngles[ ROLL ] -= side; + + side = speed * DotProduct( velocity, axis[ 0 ] ); + localAngles[ PITCH ] += side; + } + + //FIXME: PAIN[123] animations? + // pain twitch + //CG_AddPainTwitch( cent, torsoAngles ); + + AnglesToAxis( localAngles, nonSegAxis ); +} + + //========================================================================== #define JET_SPREAD 30.0f @@ -1825,6 +1984,9 @@ CG_Player void CG_Player( centity_t *cent ) { clientInfo_t *ci; + + //TA: NOTE: legs is used for nonsegmented models + // this helps reduce code to be changed refEntity_t legs; refEntity_t torso; refEntity_t head; @@ -1862,9 +2024,9 @@ void CG_Player( centity_t *cent ) return; } - memset( &legs, 0, sizeof( legs ) ); - memset( &torso, 0, sizeof( torso ) ); - memset( &head, 0, sizeof( head ) ); + memset( &legs, 0, sizeof( legs ) ); + memset( &torso, 0, sizeof( torso ) ); + memset( &head, 0, sizeof( head ) ); VectorCopy( cent->lerpAngles, angles ); AnglesToAxis( cent->lerpAngles, tempAxis ); @@ -1881,7 +2043,10 @@ void CG_Player( centity_t *cent ) angles[ PITCH ] += 360.0f; // get the rotation information - CG_PlayerAngles( cent, angles, legs.axis, torso.axis, head.axis ); + if( !ci->nonsegmented ) + CG_PlayerAngles( cent, angles, legs.axis, torso.axis, head.axis ); + else + CG_PlayerNonSegAngles( cent, angles, legs.axis ); //rotate the legs axis to back to the wall if( es->eFlags & EF_WALLCLIMB && @@ -1889,8 +2054,11 @@ void CG_Player( centity_t *cent ) AxisCopy( tempAxis, legs.axis ); // get the animation state (after rotation, to allow feet shuffle) - CG_PlayerAnimation( cent, &legs.oldframe, &legs.frame, &legs.backlerp, - &torso.oldframe, &torso.frame, &torso.backlerp ); + if( !ci->nonsegmented ) + CG_PlayerAnimation( cent, &legs.oldframe, &legs.frame, &legs.backlerp, + &torso.oldframe, &torso.frame, &torso.backlerp ); + else + CG_PlayerNonSegAnimation( cent, &legs.oldframe, &legs.frame, &legs.backlerp ); // add the talk baloon or disconnect icon CG_PlayerSprites( cent ); @@ -1911,8 +2079,16 @@ void CG_Player( centity_t *cent ) // // add the legs // - legs.hModel = ci->legsModel; - legs.customSkin = ci->legsSkin; + if( !ci->nonsegmented ) + { + legs.hModel = ci->legsModel; + legs.customSkin = ci->legsSkin; + } + else + { + legs.hModel = ci->nonSegModel; + legs.customSkin = ci->nonSegSkin; + } VectorCopy( cent->lerpOrigin, legs.origin ); @@ -1961,41 +2137,44 @@ void CG_Player( centity_t *cent ) if( !legs.hModel ) return; - // - // add the torso - // - torso.hModel = ci->torsoModel; - if( !torso.hModel ) - return; + if( !ci->nonsegmented ) + { + // + // add the torso + // + torso.hModel = ci->torsoModel; + if( !torso.hModel ) + return; - torso.customSkin = ci->torsoSkin; + torso.customSkin = ci->torsoSkin; - VectorCopy( cent->lerpOrigin, torso.lightingOrigin ); + VectorCopy( cent->lerpOrigin, torso.lightingOrigin ); - CG_PositionRotatedEntityOnTag( &torso, &legs, ci->legsModel, "tag_torso" ); + CG_PositionRotatedEntityOnTag( &torso, &legs, ci->legsModel, "tag_torso" ); - torso.shadowPlane = shadowPlane; - torso.renderfx = renderfx; + torso.shadowPlane = shadowPlane; + torso.renderfx = renderfx; - trap_R_AddRefEntityToScene( &torso ); + trap_R_AddRefEntityToScene( &torso ); - // - // add the head - // - head.hModel = ci->headModel; - if( !head.hModel ) - return; + // + // add the head + // + head.hModel = ci->headModel; + if( !head.hModel ) + return; - head.customSkin = ci->headSkin; + head.customSkin = ci->headSkin; - VectorCopy( cent->lerpOrigin, head.lightingOrigin ); + VectorCopy( cent->lerpOrigin, head.lightingOrigin ); - CG_PositionRotatedEntityOnTag( &head, &torso, ci->torsoModel, "tag_head" ); + CG_PositionRotatedEntityOnTag( &head, &torso, ci->torsoModel, "tag_head" ); - head.shadowPlane = shadowPlane; - head.renderfx = renderfx; + head.shadowPlane = shadowPlane; + head.renderfx = renderfx; - trap_R_AddRefEntityToScene( &head ); + trap_R_AddRefEntityToScene( &head ); + } // // add the gun / barrel / flash @@ -2175,6 +2354,8 @@ void CG_ResetPlayerEntity( centity_t *cent ) ¢->pe.legs, cent->currentState.legsAnim ); CG_ClearLerpFrame( &cgs.clientinfo[ cent->currentState.clientNum ], ¢->pe.torso, cent->currentState.torsoAnim ); + CG_ClearLerpFrame( &cgs.clientinfo[ cent->currentState.clientNum ], + ¢->pe.nonseg, cent->currentState.legsAnim ); BG_EvaluateTrajectory( ¢->currentState.pos, cg.time, cent->lerpOrigin ); BG_EvaluateTrajectory( ¢->currentState.apos, cg.time, cent->lerpAngles ); @@ -2194,6 +2375,12 @@ void CG_ResetPlayerEntity( centity_t *cent ) cent->pe.torso.pitchAngle = cent->rawAngles[ PITCH ]; cent->pe.torso.pitching = qfalse; + memset( ¢->pe.nonseg, 0, sizeof( cent->pe.nonseg ) ); + cent->pe.nonseg.yawAngle = cent->rawAngles[ YAW ]; + cent->pe.nonseg.yawing = qfalse; + cent->pe.nonseg.pitchAngle = cent->rawAngles[ PITCH ]; + cent->pe.nonseg.pitching = qfalse; + if( cg_debugPosition.integer ) CG_Printf( "%i ResetPlayerEntity yaw=%i\n", cent->currentState.number, cent->pe.torso.yawAngle ); } diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c index 97ef2c6a..4b8383d0 100644 --- a/src/game/bg_misc.c +++ b/src/game/bg_misc.c @@ -1309,8 +1309,8 @@ classAttributes_t bg_classList[ ] = PCL_A_O_BASE, //int classnum; "soldier", //char *classname; "Soldier", //char *humanname; - "jumper", //char *modelname; - 0.2f, //float modelScale; + "prowl", //char *modelname; + 1.0f, //float modelScale; "default", //char *skinname; "alien_hud", //char *hudname; ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages |