ValveSoftware / halflife

Half-Life 1 engine based games
Other
3.68k stars 623 forks source link

[Half-Life] Issues with weapon animations [Their Fixes Included] #2495

Open BlackShadow opened 5 years ago

BlackShadow commented 5 years ago

Hi,

Some weapons animations can't and won't animate properly because there's not enough time given to them to play it or some of them are straight broken. I'll be listing these weapons with their fixes.

Side Note: These fixes won't effect gameplay in any way. These are just cosmetic fix. These fixes make game look more proper. Also HD models are compatiable with these fixes.

RPG: RPG's fidget animation can't animate properly because there's not enough time given to it.

To fix this:

Change:

               iAnim = RPG_FIDGET;
      m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 3.0;

To:

                iAnim = RPG_FIDGET;
           m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 6.0;

Gauss: Gauss's idle animation's are completely broken. This issue appears to be in Steam version. Retail version seems to be working properly.

To fix this:

Change:

else
    {
        int iAnim;
        float flRand = RANDOM_FLOAT(0, 1);
        if (flRand <= 0.5)
        {
            iAnim = GAUSS_IDLE;
            m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
        }
        else if (flRand <= 0.75)
        {
            iAnim = GAUSS_IDLE2;
            m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
        }
        else
        {
            iAnim = GAUSS_FIDGET;
            m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 3;
        }
        return;
        SendWeaponAnim( iAnim );

    }
}

To:

if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase())
        return;

    if (m_fInAttack != 0)
    {
        StartFire();
        m_fInAttack = 0;
        m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.0;
    }

    if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase())
        return;

    int iAnim;
    float flRand = UTIL_SharedRandomFloat(m_pPlayer->random_seed, 0, 1);
    if (flRand <= 0.75)
    {
        iAnim = GAUSS_IDLE;
        m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 80.0 / 15.6 * (2);
    }
    else if (flRand <= 0.875)
    {
        iAnim = GAUSS_IDLE2;
        m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 80.0 / 19.0;
    }
    else
    {
        iAnim = GAUSS_FIDGET;
        m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 85.0 / 15.0;
    }
    SendWeaponAnim(iAnim);
}

Hand Grenade: Hand Grenade is supposed to play HANDGRENADE_DRAW animation after player threw a grenade.

Commenting out "m_flReleaseThrow = 0;" fixes our issue. Thanks to @SamVanHeer pointing this out.

    ```
        //m_flReleaseThrow = 0;
    m_flStartThrow = 0;
    m_flNextPrimaryAttack = GetNextAttackDelay(0.5);
    m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.5;
            ```

However after player ran out of grenades and pick up a grenade, it won't show up until player switch weapons.

We can easily fix this issue by removing " RetireWeapon(); "


if ( m_pPlayer->m_rgAmmo[ m_iPrimaryAmmoType ] )
        {
            SendWeaponAnim( HANDGRENADE_DRAW );
        }
        else
        {
            RetireWeapon(); //Delete this
            return;
        }

Satchel and Snark (Squeak):

Satchel can't animate it's draw animation properly. This issue happens in Snark as well.

in weapons.cpp:

BOOL CBasePlayerWeapon :: DefaultDeploy( char *szViewModel, char *szWeaponModel, int iAnim, char *szAnimExt, int skiplocal /* = 0 */, int body )
{
    if (!CanDeploy( ))
        return FALSE;

    m_pPlayer->TabulateAmmo();
    m_pPlayer->pev->viewmodel = MAKE_STRING(szViewModel);
    m_pPlayer->pev->weaponmodel = MAKE_STRING(szWeaponModel);
    strcpy( m_pPlayer->m_szAnimExtention, szAnimExt );
    SendWeaponAnim( iAnim, skiplocal, body );

    m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
    m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.0; //Change 1.0 to 3.0
    m_flLastFireTime = 0.0;

    return TRUE;
}

This fixes draw animation problem. All i did was change, "m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.0;" to "m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 3.0;"

This gives enough time to play draw animation to these weapons.

SamVanheer commented 5 years ago

Be very careful when changing variables in weapons code, any change in timing could have unexpected side-effects.

BlackShadow commented 5 years ago

@SamVanheer I can confirm these fixes are tested and doesn't break any weapons.

ExpertPizzaTipper commented 5 years ago

The crowbar never plays it's idle animations.

CS-PRO1 commented 5 years ago

There's also the crowbar idle animations and the tripmines attaching animations (sequence names: arm1 and place)

BlackShadow commented 5 years ago

@Don576 I'll look into that

@CS-PRO1 Those animations are beta animations, Valve dropped those animations during development.

More info : https://youtu.be/e59bvmvXPk0?t=202

CS-PRO1 commented 5 years ago

They're still not cut tho. Maybe they were intended to be in the final one. Or maybe implement just "place" and drop "arm1"

BlackShadow commented 5 years ago

@CS-PRO1 They're "leftover" from beta. These are common things in development. Devs became lazy or rush things and forgot delete those kinds of things. That's why they called "leftover".

BlackShadow commented 5 years ago

I looked up idle animations of Crowbar and it seems Valve never implemented them. I don't really know if Valve dropped the idea during development or forgot adding them.

CS-PRO1 commented 5 years ago

I looked up idle animations of Crowbar and it seems Valve never implemented them. I don't really know if Valve dropped the idea during development or forgot adding them.

I don't think so, in HL:S they work as intended.

SamVanheer commented 5 years ago

Note that the Crowbar doesn't have a WeaponIdle method at all, and the Source SDK handles it by using a common base class that looks up animations by act, so that could just be an unintentional side-effect rather than intended behavior.

CS-PRO1 commented 5 years ago

I've seen SC had fixed Idle for crowbar but I dunno if it's possible to implement in HL tho.

BlackShadow commented 5 years ago

It's possible, but they didn't added. As the Sam said they not even added WeaponIdle and this made me think straight away they cut the crowbar animations.

OpenRift412 commented 3 years ago

Gauss: Gauss's idle animation's are completely broken. This issue appears to be in Steam version. Retail version seems to be working properly.

I tested this in versions 1.0.1.6 and 1.0.0.5 (release build), and there didn't appear to be an idle animation for the Tau Cannon/Gauss. Perhaps this was an unused animation, like the one for the crowbar?

EDIT: Also checked version 1.1.1.0 of the WON (Retail) version, also doesn't appear to be present there either.

BlackShadow commented 3 years ago

Gauss: Gauss's idle animation's are completely broken. This issue appears to be in Steam version. Retail version seems to be working properly.

I tested this in versions 1.0.1.6 and 1.0.0.5 (release build), and there didn't appear to be an idle animation for the Tau Cannon/Gauss. Perhaps this was an unused animation, like the one for the crowbar?

EDIT: Also checked version 1.1.1.0 of the WON (Retail) version, also doesn't appear to be present there either.

Judging from code Gauss's idle animations are intended because it has WeaponIdle. It doesn't work because of strings are missing.

SamVanheer commented 3 years ago

The Gauss's idle animations are disabled because there's a return statement before SendWeaponAnim: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/gauss.cpp#L568-L590

It's been like that since SDK 1.0 so it's probably intentional.

BlackShadow commented 3 years ago

BUGBUGBUG - Only bug i could found with this fix is Shotgun continues to reload delayed when weapons switched during reload.

This happens because Shotgun's reload depends on m_flTimeWeaponIdle = UTIL_WeaponTimeBase()

And the reason why it's happens because we've changed m_flTimeWeaponIdle = UTIL_WeaponTimeBase() time to 3.0 from 1.0 And that makes Shotgun reload is a bit delayed. I've tried few things but i couldn't find a proper fix.

OpenRift412 commented 3 years ago

BUGBUGBUG - Only bug i could found with this fix is Shotgun continues to reload delayed when weapons switched during reload.

This happens because Shotgun's reload depends on m_flTimeWeaponIdle = UTIL_WeaponTimeBase()

This is happens because we changed m_flTimeWeaponIdle = UTIL_WeaponTimeBase() time to 3.0 from 1.0 And that makes Shotgun reload is a bit delayed. I've tried few things to fix this but i couldn't fix a proper fix.

I did notice this as well. Hopefully someone finds a fix for this.

SamVanheer commented 3 years ago

BUGBUGBUG - Only bug i could found with this fix is Shotgun continues to reload delayed when weapons switched during reload.

This happens because Shotgun's reload depends on m_flTimeWeaponIdle = UTIL_WeaponTimeBase()

And the reason why it's happens because we've changed m_flTimeWeaponIdle = UTIL_WeaponTimeBase() time to 3.0 from 1.0 And that makes Shotgun reload is a bit delayed. I've tried few things but i couldn't find a proper fix.

My recommendation is to not change DefaultDeploy and instead changing the idle time separately in those weapons that need a different delay. That way other weapons are unaffected.

OpenRift412 commented 3 years ago

BUGBUGBUG - Only bug i could found with this fix is Shotgun continues to reload delayed when weapons switched during reload. This happens because Shotgun's reload depends on m_flTimeWeaponIdle = UTIL_WeaponTimeBase() And the reason why it's happens because we've changed m_flTimeWeaponIdle = UTIL_WeaponTimeBase() time to 3.0 from 1.0 And that makes Shotgun reload is a bit delayed. I've tried few things but i couldn't find a proper fix.

My recommendation is to not change DefaultDeploy and instead changing the idle time separately in those weapons that need a different delay. That way other weapons are unaffected.

How would you do that? I'm new to this sorta stuff, so I wouldn't know.

SamVanheer commented 3 years ago
if (DefaultDeploy(stuff))
{
    m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 3.0;
}
OpenRift412 commented 3 years ago
if (DefaultDeploy(stuff))
{
    m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 3.0;
}

What would I put in the place of "stuff"? Would I be replacing szViewModel, szWeaponModel, etc. with specific weapon names?

SamVanheer commented 3 years ago

Using the satchel as an example: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/satchel.cpp#L292-L305

Modify it to look like this:

BOOL CSatchel::Deploy( )
{

    m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1.0;
    //m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );

    BOOL result = FALSE;

    if ( m_chargeReady )
        result = DefaultDeploy( "models/v_satchel_radio.mdl", "models/p_satchel_radio.mdl", SATCHEL_RADIO_DRAW, "hive" );
    else
        result = DefaultDeploy( "models/v_satchel.mdl", "models/p_satchel.mdl", SATCHEL_DRAW, "trip" );

    if (result)
    {
        m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 3;
    }

    return result;
}

Note how i've commented out the first assignment since the value is overwritten anyway. I've also replaced the return statement on the last line since that line was never reached before.

Also keep in mind that some weapon functions are duplicated on the client side for prediction: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/cl_dll/hl/hl_weapons.cpp#L211-L224

If you modify the server side you also need to modify the client side so everything stays in sync.

OpenRift412 commented 3 years ago

So then for the snark, it would change from this:

BOOL CSqueak::Deploy( ) { // play hunt sound float flRndSound = RANDOM_FLOAT ( 0 , 1 );

if ( flRndSound <= 0.5 ) EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/sqk_hunt2.wav", 1, ATTN_NORM, 0, 100); else EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/sqk_hunt3.wav", 1, ATTN_NORM, 0, 100);

m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME;

return DefaultDeploy( "models/v_squeak.mdl", "models/p_squeak.mdl", SQUEAK_UP, "squeak" ); }

To this?

BOOL CSqueak::Deploy( ) { // play hunt sound float flRndSound = RANDOM_FLOAT ( 0 , 1 );

if ( flRndSound <= 0.5 ) EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/sqk_hunt2.wav", 1, ATTN_NORM, 0, 100); else EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/sqk_hunt3.wav", 1, ATTN_NORM, 0, 100); if (result) { m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 3; }

m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME;

return result; }

Am I getting this right?

SamVanheer commented 3 years ago

No.

BOOL CSqueak::Deploy( )
{
    // play hunt sound
    float flRndSound = RANDOM_FLOAT ( 0 , 1 );

    if ( flRndSound <= 0.5 )
        EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/sqk_hunt2.wav", 1, ATTN_NORM, 0, 100);
    else 
        EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/sqk_hunt3.wav", 1, ATTN_NORM, 0, 100);

    m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME;

    BOOL result = DefaultDeploy( "models/v_squeak.mdl", "models/p_squeak.mdl", SQUEAK_UP, "squeak" );

    if (result)
    {
        m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 3;
    }

    return result;
}

I'd suggest learning C++ before trying to figure stuff like this out, you really need to understand what's going on to fix stuff like this.

OpenRift412 commented 3 years ago

I'd suggest learning C++ before trying to figure stuff like this out, you really need to understand what's going on to fix stuff like this.

I learn better by example. Thanks for the clarification though.

SamVanheer commented 3 years ago

A few notes:

Instead of commenting out RetireWeapon for the hand grenade the code for that should be changed to handle exhaustible weapons properly in general.

Modify this: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/weapons.cpp#L1182-L1190

To include this:

void CBasePlayerWeapon::RetireWeapon()
{
    // first, no viewmodel at all.
    m_pPlayer->pev->viewmodel = iStringNull;
    m_pPlayer->pev->weaponmodel = iStringNull;
    //m_pPlayer->pev->viewmodelindex = NULL;

    g_pGameRules->GetNextBestWeapon( m_pPlayer, this );

    //If we're still equipped and we couldn't switch to another weapon, dequip this one
    if (CanHolster() && m_pPlayer->m_pActiveItem == this)
    {
        m_pPlayer->SwitchWeapon(nullptr);
    }
}

And modify this: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/player.cpp#L4648-L4666

To include this:

BOOL CBasePlayer :: SwitchWeapon( CBasePlayerItem *pWeapon ) 
{
    if (pWeapon && !pWeapon->CanDeploy() )
    {
        return FALSE;
    }

    ResetAutoaim( );

    if (m_pActiveItem)
    {
        m_pActiveItem->Holster( );
    }

    m_pActiveItem = pWeapon;

    if (pWeapon)
    {
        pWeapon->Deploy();
    }

    return TRUE;
}

This allows switching to no weapon. When a weapon is retired, if the player still has it equipped after an attempted switch to next best weapon and the current weapon can be holstered the player's current weapon will be holstered.

If you then pick up ammo for that weapon it will be deployed as usual.

See also #3073 for a bug affecting Snark primary attack and #3069 for a bug that can cause the Snark's deploy animation to not play sometimes.

mr-sihc commented 3 years ago

@kisak-valve DONT FORGET DIS and could someone open a pull request or something pls?