diff --git a/modules/cstrike/cstrike/CstrikeNatives.cpp b/modules/cstrike/cstrike/CstrikeNatives.cpp index 1940abbf..5d5ad4d2 100644 --- a/modules/cstrike/cstrike/CstrikeNatives.cpp +++ b/modules/cstrike/cstrike/CstrikeNatives.cpp @@ -189,18 +189,19 @@ static cell AMX_NATIVE_CALL cs_set_weapon_silenced(AMX *amx, cell *params) CHECK_NONPLAYER(index); edict_t *pWeapon = INDEXENT(index); - bool draw_animation = true; + int draw_animation = 1; if ((params[0] / sizeof(cell)) >= 3) { - draw_animation = params[3] != 0; + draw_animation = params[3]; } + int weaponType = get_pdata(pWeapon, m_iId); int weaponState = get_pdata(pWeapon, m_iWeaponState); int weaponNewState = weaponState; int animation = 0; - switch (get_pdata(pWeapon, m_iId)) + switch (weaponType) { case CSW_M4A1: { @@ -236,9 +237,61 @@ static cell AMX_NATIVE_CALL cs_set_weapon_silenced(AMX *amx, cell *params) { set_pdata(pWeapon, m_iWeaponState, weaponNewState); - if (draw_animation && UTIL_IsPlayer(pWeapon->v.owner)) + edict_t *pPlayer = pWeapon->v.owner; + + if (draw_animation > 0 && UTIL_IsPlayer(pPlayer)) { - pWeapon->v.owner->v.weaponanim = animation; + int currentWeapon = *static_cast(MF_PlayerPropAddr(ENTINDEX(pPlayer), Player_CurrentWeapon)); + + if (currentWeapon != weaponType) + { + return 1; + } + + pPlayer->v.weaponanim = animation; + + if (draw_animation >= 2) + { + // Skip if cl_lw client cvar (client-side weapon firing prediction) is set. + // Technically, this should be associated to UseDecrement(), but it's true by default in game at compilation. + if (!ENGINE_CANSKIP(pPlayer)) + { + MESSAGE_BEGIN(MSG_ONE, SVC_WEAPONANIM, nullptr, pPlayer); + WRITE_BYTE(animation); + WRITE_BYTE(pWeapon->v.body); + MESSAGE_END(); + } + + GET_OFFSET("CBasePlayer", m_szAnimExtention); + GET_OFFSET("CBasePlayerWeapon", m_flTimeWeaponIdle); + GET_OFFSET("CBasePlayerWeapon", m_flNextSecondaryAttack); + GET_OFFSET("CBasePlayerWeapon", m_flNextPrimaryAttack); + + char animExt[12]; + float time; + + switch (weaponType) + { + case CSW_M4A1: + { + strcpy(animExt, "rifle"); + time = 2.0f; + break; + } + case CSW_USP: + { + strcpy(animExt, "onehanded"); + time = 3.0f; + break; + } + } + + set_pdata(pPlayer, m_szAnimExtention, STRING(MAKE_STRING(animExt))); + + set_pdata(pWeapon, m_flTimeWeaponIdle, time); + set_pdata(pWeapon, m_flNextSecondaryAttack, time); + set_pdata(pWeapon, m_flNextPrimaryAttack, time); + } } return 1; diff --git a/plugins/include/cstrike.inc b/plugins/include/cstrike.inc index 8d3e93a3..d33645b6 100755 --- a/plugins/include/cstrike.inc +++ b/plugins/include/cstrike.inc @@ -698,9 +698,12 @@ native cs_get_weapon_silen(index); * @param index Weapon entity index * @param silence If nonzero the weapon will be put into silenced * mode, otherwise the silenced mode will be removed - * @param draw_animation If nonzero and the weapon is currently held by a + * @param draw_animation If 1 and the weapon is currently held by a * client, the appropriate weapon animation will be * played + * If 2, same as 1 but follows game behavior by playing + * the associated player's model sequence and disallowing + * firing while animation is playing. * * @return 1 if silenced mode set successfully, 0 if entity is * not an applicable weapon