Hi, I'm testing a plugin where the player model is changed by a new model, and I change the model by this way:
PHP Code:
// I'm using the way to prevent SVC_BAD error.
public fm_set_user_model( taskid )
{
if( is_valid_player( ID_MODEL ) )
{
set_user_info(ID_MODEL, "model", g_player_model[ ID_MODEL ]);
new szModel[ 128 ];
formatex( szModel, sizeof szModel - 1, "models/player/%s/%s.mdl",
g_player_model[ ID_MODEL ], g_player_model[ ID_MODEL ] );
new indexMdl = engfunc( EngFunc_ModelIndex, szModel );
set_pdata_int( ID_MODEL, m_iModelIndex, indexMdl );
}
}
The player's model has a new list of sequences, the default CS have 111 sequences for each player, and this new model has 39 sequences.
The sequences play fine, I'm using the offset m_szAnimExtention for force the CS to play some animations like ref_aim, ref_shoot, crouch_aim, crouch_shoot. But I tested taking the use of this offset off, but it wasn't the problem.
The problem is the following:
When the player dies, how it was, this doesn't matter, the upper part of the body ( controlled by pev_sequence ) is played, the arms and head moves like he is dying, but the lower part of the body doesn't move, it stays like in "dummy" animation. I made some tests handling the SetAnimation function with Orpheu, and I did some prints that reported the states of:
* the parameter of SetAnimation function "PLAYER_ANIM"
* m_Activity offset
* pev->sequence
* pev->gaitsequence
and the values were the same, except pev_sequence, that is because the number of the animation where "dies" sequences resides arent the same because the default player has 111 sequences and this new model has 39 sequences.
when Player dies with the default cs model:
gaitsequence = 0
when player dies with the new model:
gaitsequence = 0
So, the SetAnimation function place it at "dummy" sequence, I can't understand how the CS makes to move all the body when the player dies, and it doesn't stays with the legs at the state of "dummy" sequence.
I will let some pictures just here:
Can you see how the model stays with the legs like in "dummy" sequence.
It is because the SetAnimation functions set pev_gaitsequence = 0 when player dies, but the default CS moves all body, and the value of gaitsequence is the same that with this plugin.
+Data:
PHP Code:
void CBasePlayer::Killed( entvars_t *pevAttacker, int iGib )
{
CSound *pSound;
// Holster weapon immediately, to allow it to cleanup
if ( m_pActiveItem )
m_pActiveItem->Holster( );
g_pGameRules->PlayerKilled( this, pevAttacker, g_pevLastInflictor );
if ( m_pTank != NULL )
{
m_pTank->Use( this, this, USE_OFF, 0 );
m_pTank = NULL;
}
// this client isn't going to be thinking for a while, so reset the sound until they respawn
pSound = CSoundEnt::SoundPointerForIndex( CSoundEnt::ClientSoundIndex( edict() ) );
{
if ( pSound )
{
pSound->Reset();
}
}
SetAnimation( PLAYER_DIE );
m_iRespawnFrames = 0;
pev->modelindex = g_ulModelIndexPlayer; // don't use eyes
pev->deadflag = DEAD_DYING;
pev->movetype = MOVETYPE_TOSS;
ClearBits( pev->flags, FL_ONGROUND );
if (pev->velocity.z < 10)
pev->velocity.z += RANDOM_FLOAT(0,300);
// clear out the suit message cache so we don't keep chattering
SetSuitUpdate(NULL, FALSE, 0);
// send "health" update message to zero
m_iClientHealth = 0;
MESSAGE_BEGIN( MSG_ONE, gmsgHealth, NULL, pev );
WRITE_BYTE( m_iClientHealth );
MESSAGE_END();
// Tell Ammo Hud that the player is dead
MESSAGE_BEGIN( MSG_ONE, gmsgCurWeapon, NULL, pev );
WRITE_BYTE(0);
WRITE_BYTE(0XFF);
WRITE_BYTE(0xFF);
MESSAGE_END();
// reset FOV
pev->fov = m_iFOV = m_iClientFOV = 0;
MESSAGE_BEGIN( MSG_ONE, gmsgSetFOV, NULL, pev );
WRITE_BYTE(0);
MESSAGE_END();
// UNDONE: Put this in, but add FFADE_PERMANENT and make fade time 8.8 instead of 4.12
// UTIL_ScreenFade( edict(), Vector(128,0,0), 6, 15, 255, FFADE_OUT | FFADE_MODULATE );
if ( ( pev->health < -40 && iGib != GIB_NEVER ) || iGib == GIB_ALWAYS )
{
pev->solid = SOLID_NOT;
GibMonster(); // This clears pev->model
pev->effects |= EF_NODRAW;
return;
}
DeathSound();
pev->angles.x = 0;
pev->angles.z = 0;
SetThink(PlayerDeathThink);
pev->nextthink = gpGlobals->time + 0.1;
}
PHP Code:
// Set the activity based on an event or current state
void CBasePlayer::SetAnimation( PLAYER_ANIM playerAnim )
{
int animDesired;
float speed;
char szAnim[64];
speed = pev->velocity.Length2D();
if (pev->flags & FL_FROZEN)
{
speed = 0;
playerAnim = PLAYER_IDLE;
}
switch (playerAnim)
{
case PLAYER_JUMP:
m_IdealActivity = ACT_HOP;
break;
case PLAYER_SUPERJUMP:
m_IdealActivity = ACT_LEAP;
break;
case PLAYER_DIE:
m_IdealActivity = ACT_DIESIMPLE;
m_IdealActivity = GetDeathActivity( );
break;
case PLAYER_ATTACK1:
switch( m_Activity )
{
case ACT_HOVER:
case ACT_SWIM:
case ACT_HOP:
case ACT_LEAP:
case ACT_DIESIMPLE:
m_IdealActivity = m_Activity;
break;
default:
m_IdealActivity = ACT_RANGE_ATTACK1;
break;
}
break;
case PLAYER_IDLE:
case PLAYER_WALK:
if ( !FBitSet( pev->flags, FL_ONGROUND ) && (m_Activity == ACT_HOP || m_Activity == ACT_LEAP) ) // Still jumping
{
m_IdealActivity = m_Activity;
}
else if ( pev->waterlevel > 1 )
{
if ( speed == 0 )
m_IdealActivity = ACT_HOVER;
else
m_IdealActivity = ACT_SWIM;
}
else
{
m_IdealActivity = ACT_WALK;
}
break;
}
switch (m_IdealActivity)
{
case ACT_HOVER:
case ACT_LEAP:
case ACT_SWIM:
case ACT_HOP:
case ACT_DIESIMPLE:
default:
if ( m_Activity == m_IdealActivity)
return;
m_Activity = m_IdealActivity;
animDesired = LookupActivity( m_Activity );
// Already using the desired animation?
if (pev->sequence == animDesired)
return;
pev->gaitsequence = 0;
pev->sequence = animDesired;
pev->frame = 0;
ResetSequenceInfo( );
return;
case ACT_RANGE_ATTACK1:
if ( FBitSet( pev->flags, FL_DUCKING ) ) // crouching
strcpy( szAnim, "crouch_shoot_" );
else
strcpy( szAnim, "ref_shoot_" );
strcat( szAnim, m_szAnimExtention );
animDesired = LookupSequence( szAnim );
if (animDesired == -1)
animDesired = 0;
if ( pev->sequence != animDesired || !m_fSequenceLoops )
{
pev->frame = 0;
}
if (!m_fSequenceLoops)
{
pev->effects |= EF_NOINTERP;
}
m_Activity = m_IdealActivity;
pev->sequence = animDesired;
ResetSequenceInfo( );
break;
case ACT_WALK:
if (m_Activity != ACT_RANGE_ATTACK1 || m_fSequenceFinished)
{
if ( FBitSet( pev->flags, FL_DUCKING ) ) // crouching
strcpy( szAnim, "crouch_aim_" );
else
strcpy( szAnim, "ref_aim_" );
strcat( szAnim, m_szAnimExtention );
animDesired = LookupSequence( szAnim );
if (animDesired == -1)
animDesired = 0;
m_Activity = ACT_WALK;
}
else
{
animDesired = pev->sequence;
}
}
if ( FBitSet( pev->flags, FL_DUCKING ) )
{
if ( speed == 0)
{
pev->gaitsequence = LookupActivity( ACT_CROUCHIDLE );
// pev->gaitsequence = LookupActivity( ACT_CROUCH );
}
else
{
pev->gaitsequence = LookupActivity( ACT_CROUCH );
}
}
else if ( speed > 220 )
{
pev->gaitsequence = LookupActivity( ACT_RUN );
}
else if (speed > 0)
{
pev->gaitsequence = LookupActivity( ACT_WALK );
}
else
{
// pev->gaitsequence = LookupActivity( ACT_WALK );
pev->gaitsequence = LookupSequence( "deep_idle" );
}
// Already using the desired animation?
if (pev->sequence == animDesired)
return;
//ALERT( at_console, "Set animation to %d\n", animDesired );
// Reset to first frame of desired animation
pev->sequence = animDesired;
pev->frame = 0;
ResetSequenceInfo( );
}
Greetings!
__________________