PushAbility.cs
using Sandbox;
using System;
using System.Threading.Tasks;

public sealed class PushAbility : Component
{
    [Property] public float PushForce { get; set; } = 20000f;
    [Property] public float PushRadius { get; set; } = 300f;
    [Property] public float Cooldown { get; set; } = 0.5f;

    // Эффекты
    [Property] public GameObject PushParticle { get; set; }
    [Property] public SoundEvent PushSound { get; set; }

    private TimeSince _lastPush;

    public float CooldownProgress => MathF.Min( _lastPush / Cooldown, 1f );
    public bool IsReady => _lastPush >= Cooldown;

    protected override void OnUpdate()
    {
        if ( Input.Pressed( "attack1" ) && _lastPush > Cooldown )
        {
            _lastPush = 0;
            ExecutePush();
        }
    }

    private void ExecutePush()
    {
        Log.Info( "Толчок сработал!" );

        if ( PushParticle.IsValid() )
        {
            var p = PushParticle.Clone( WorldPosition );
            _ = DestroyAfterDelay( p, 2000 );
        }

        if ( PushSound != null )
        {
            Sound.Play( PushSound, WorldPosition );
        }

        var startPos = WorldPosition;
        var endPos = WorldPosition + Vector3.Up * 1f;

        var hits = Scene.Trace.Sphere( PushRadius, startPos, endPos )
            .IgnoreGameObject( GameObject )
            .RunAll();

        // Получаем множитель силы от выбранного в магазине предмета (по умолчанию 1.0)
        float mult = ShopManager.Instance?.GetCurrentForceMultiplier() ?? 1.0f;
        float currentPushForce = PushForce * mult;

        foreach ( var hit in hits )
        {
            if ( !hit.GameObject.IsValid() ) continue;

            var rb = hit.GameObject.Components.Get<Rigidbody>();
            if ( rb.IsValid() )
            {
                var direction = (hit.GameObject.WorldPosition - WorldPosition).Normal;
                direction.z = 0.4f;

                // Применяем итоговую силу с учетом множителя
                rb.ApplyImpulse( direction * currentPushForce );
                Log.Info( $"Толкнули объект: {hit.GameObject.Name} с силой {currentPushForce}" );
            }
        }
    }

    private async Task DestroyAfterDelay( GameObject obj, int delayMs )
    {
        await Task.Delay( delayMs );

        if ( obj.IsValid() )
        {
            obj.Destroy();
        }
    }
}