```lua
-- lua/weapons/custom_weapon/shared.lua
SWEP.PrintName = "Кастомное Оружие"
SWEP.Author = "ВашеИмя"
SWEP.Instructions = "Левый клик для стрельбы."
SWEP.Spawnable = true
SWEP.AdminOnly = false
-- Настройка боеприпасов
SWEP.Primary.ClipSize = 7 -- Размер магазина
SWEP.Primary.DefaultClip = 8 -- 7 в магазине + 1 в патронник
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = "Pistol" -- Тип боеприпасов
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"
-- Отключаем стандартные руки и ViewModel
SWEP.UseHands = false
SWEP.ViewModel = "" -- Оставьте пустым для отключения
SWEP.ViewModelFOV = 54
-- Указываем модель для мира (что видят другие игроки)
SWEP.WorldModel = "models/deadfall/weapons/fb wz,35 vis.mdl" -- Укажите правильный путь к модели
-- Установка типа хватки
function SWEP:Initialize()
    self:SetHoldType("pistol") -- Устанавливаем начальный тип хватки
    if CLIENT then
        self.ShowAmmoStartTime = 0 -- Время начала отображения текста
        self.ShowAmmoDuration = 3 -- Время, в течение которого текст полностью видим (без учета фейдов)
        self.FadeTime = 1 -- Время фейда (плавного появления и исчезновения)
        self.CurrentHoldType = "pistol" -- Переменная для отслеживания текущего типа хватки
    end
end

-- Деплой оружия
function SWEP:Deploy()
    if CLIENT then self:CreateWeaponModel() end
    self:SendWeaponAnim(ACT_VM_DRAW)
    return true
end

-- Основная логика при первичной атаке (стрельба)
function SWEP:PrimaryAttack()
    if not self:CanPrimaryAttack() then return end
    self:SetNextPrimaryFire(CurTime() + self:GetPrimaryFireDelay())
    local owner = self:GetOwner()
    if not IsValid(owner) then return end
    -- Воспроизвести звуковой эффект
    self:EmitSound("Weapon_Pistol.Single")
    -- Воспроизвести анимацию выстрела
    self:SendWeaponAnim(ACT_VM_PRIMARYATTACK)
    owner:SetAnimation(PLAYER_ATTACK1) -- Анимация игрока при выстреле
    -- Уменьшаем количество патронов в магазине
    self:TakePrimaryAmmo(1)
    -- Эффект выстрела (Muzzle Flash)
    if CLIENT then
        local vm = owner:GetViewModel()
        if IsValid(vm) then
            local attachmentID = vm:LookupAttachment("1") -- Обычно "1" это muzzle
            local attachment = vm:GetAttachment(attachmentID)
            if attachment then
                local effect = EffectData()
                effect:SetOrigin(attachment.Pos)
                effect:SetAngles(attachment.Ang)
                effect:SetScale(1)
                util.Effect("MuzzleFlash", effect)
            end
        end
    end

    -- Логика выстрела пули со всеми эффектами
    if SERVER then
        local bullet = {}
        bullet.Num = 1
        bullet.Src = owner:GetShootPos() -- Позиция вылета пули
        bullet.Dir = owner:GetAimVector() -- Направление вылета пули
        bullet.Spread = Vector(0, 0, 0) -- Разброс (измените при необходимости)
        bullet.Tracer = 1 -- Частота появления трассеров (1 = каждый выстрел)
        bullet.TracerName = "Tracer" -- Эффект трассера ("Tracer" - стандартный)
        bullet.Force = 5 -- Сила попадания
        bullet.Damage = 10 -- Урон
        bullet.AmmoType = self.Primary.Ammo
        owner:FireBullets(bullet)
    end
end

-- Задержка между выстрелами
function SWEP:GetPrimaryFireDelay()
    return 0.5 -- Задержка между выстрелами в секундах
end

-- Проверка возможности атаки
function SWEP:CanPrimaryAttack()
    if self:Clip1() <= 0 then
        self:EmitSound("Weapon_Pistol.Empty") -- Звук пустого магазина
        self:SetNextPrimaryFire(CurTime() + 0.2) -- Небольшая задержка перед следующим действием
        return false
    end
    return true
end

-- Действие при вторичной атаке
function SWEP:SecondaryAttack()
    -- Если вторичная атака не используется, оставьте пустым
    -- Hold type изменяется динамически в функции Think()
end

-- Функция перезарядки оружия
function SWEP:Reload()
    local owner = self:GetOwner()
    if owner:KeyDown(IN_ATTACK) then -- Не перезаряжаться при атаке
        return
    end

    if self:Clip1() >= self.Primary.ClipSize then -- Магазин полон
        return
    end

    if owner:GetAmmoCount(self.Primary.Ammo) <= 0 then -- Нет боеприпасов
        return
    end

    self:DefaultReload(ACT_VM_RELOAD)
    self:EmitSound("Weapon_Pistol.Reload") -- Звук перезарядки
    self:SetNextPrimaryFire(CurTime() + 2) -- Устанавливаем задержку на время перезарядки
    owner:SetAnimation(PLAYER_RELOAD) -- Анимация перезарядки для игрока
end
```
```lua
-- lua/weapons/custom_weapon/init.lua

AddCSLuaFile("shared.lua")
AddCSLuaFile("cl_init.lua")

include("shared.lua")

-- Здесь можно добавить серверные специфичные функции, если они понадобятся

-- Например, дополнительные проверки безопасности или логика управления оружием
```
```lua
-- lua/weapons/custom_weapon/cl_init.lua
include("shared.lua")
-- Создание клиентской модели оружия
function SWEP:CreateWeaponModel()
    if IsValid(self.WeaponModel) then return end
    self.WeaponModel = ClientsideModel(self.WorldModel)
    if IsValid(self.WeaponModel) then
        self.WeaponModel:SetNoDraw(true)
    else
        print("Ошибка: Не удалось создать клиентскую модель оружия по пути " .. self.WorldModel)
    end
end

-- Обновление позиции и углов модели оружия
function SWEP:UpdateWeaponModel()
    if not IsValid(self.WeaponModel) or not IsValid(self:GetOwner()) then return end
    local owner = self:GetOwner()
    local boneIndex = owner:LookupBone("ValveBiped.Bip01_R_Hand") -- Кость правой руки
    if not boneIndex then return end
    local boneMatrix = owner:GetBoneMatrix(boneIndex)
    if not boneMatrix then return end
    local pos, ang = boneMatrix:GetTranslation(), boneMatrix:GetAngles()
    -- Настройка углов поворота для правильного отображения модели
    ang:RotateAroundAxis(ang:Forward(), 10)
    ang:RotateAroundAxis(ang:Right(), 180)
    ang:RotateAroundAxis(ang:Up(), 180)
    -- Настройка позиции относительно кости руки
    pos = pos + ang:Forward() * -1.5 + ang:Right() * -2 + ang:Up() * 2.3
    self.WeaponModel:SetRenderOrigin(pos)
    self.WeaponModel:SetRenderAngles(ang)
end

-- Функция Think для отслеживания нажатия клавиши R (перезарядки) и изменения типа хватки
function SWEP:Think()
    -- Существующая логика отображения патронов при перезарядке
    if self.ShowAmmoStartTime == nil then self.ShowAmmoStartTime = 0 end
    if self:GetOwner():KeyPressed(IN_RELOAD) then
        self.ShowAmmoStartTime = CurTime() -- Начало отображения текста
    end

    -- Логика для изменения типа хватки при нажатии правой кнопки мыши
    local owner = self:GetOwner()
    if IsValid(owner) then
        if owner:KeyDown(IN_ATTACK2) then -- Проверяем, удерживается ли правая кнопка мыши
            if self.CurrentHoldType ~= "revolver" then
                self:SetHoldType("revolver") -- Меняем тип хватки на "revolver"
                self.CurrentHoldType = "revolver" -- Обновляем текущий тип хватки
            end
        else
            if self.CurrentHoldType ~= "pistol" then
                self:SetHoldType("pistol") -- Возвращаем тип хватки на "pistol"
                self.CurrentHoldType = "pistol" -- Обновляем текущий тип хватки
            end
        end
    end

    -- Логика отображения 3D текста с количеством патронов
    local currentTime = CurTime()
    local elapsedTime = currentTime - self.ShowAmmoStartTime
    local totalDisplayTime = self.ShowAmmoDuration + 2 * self.FadeTime -- Общее время отображения текста
    if elapsedTime < 0 or elapsedTime > totalDisplayTime then
        return
    else
        -- Вычисляем альфа-канал для плавного появления и исчезновения
        local alpha = 255
        if elapsedTime < self.FadeTime then
            -- Фаза плавного появления
            alpha = Lerp(elapsedTime / self.FadeTime, 0, 255)
        elseif elapsedTime > (self.ShowAmmoDuration + self.FadeTime) then
            -- Фаза плавного исчезновения
            local fadeOutTime = elapsedTime - (self.ShowAmmoDuration + self.FadeTime)
            alpha = Lerp(fadeOutTime / self.FadeTime, 255, 0)
        else
            alpha = 255 -- Полностью видимый текст
        end

        if not IsValid(owner) then return end
        local boneIndex = owner:LookupBone("ValveBiped.Bip01_R_Hand")
        if not boneIndex then return end
        local bonePos, boneAng = owner:GetBonePosition(boneIndex)
        -- Настройка позиции текста относительно руки
        local offset = Vector(0, 10, -5)
        local textPos = bonePos + boneAng:Right() * offset.x + boneAng:Forward() * offset.y + boneAng:Up() * offset.z
        -- Настройка угла поворота текста
        local textAng = boneAng
        textAng:RotateAroundAxis(boneAng:Right(), 90)
        textAng:RotateAroundAxis(boneAng:Up(), 90)
        textAng:RotateAroundAxis(boneAng:Forward(), 0)
        -- Отрисовка 3D текста
        cam.Start3D2D(textPos, textAng, 0.1)
        draw.SimpleText("Патроны: " .. self:Clip1() .. "/" .. owner:GetAmmoCount(self.Primary.Ammo), "DermaLarge", 0, 0, Color(255, 255, 255, alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
        cam.End3D2D()
    end
end

-- Отрисовка модели оружия в мире и 3D текста с количеством патронов
function SWEP:DrawWorldModel()
    -- Сначала отрисовываем модель оружия
    if not IsValid(self.WeaponModel) then
        self:CreateWeaponModel()
        if not IsValid(self.WeaponModel) then return end
    end

    if IsValid(self:GetOwner()) then
        self:UpdateWeaponModel()
        self.WeaponModel:DrawModel()
    else
        self:DrawModel()
    end

    -- Затем отрисовываем 3D текст с количеством патронов, если время отображения не истекло
    local currentTime = CurTime()
    local elapsedTime = currentTime - self.ShowAmmoStartTime
    local totalDisplayTime = self.ShowAmmoDuration + 2 * self.FadeTime -- Общее время отображения текста
    if elapsedTime < 0 or elapsedTime > totalDisplayTime then
        return -- Не отображаем текст
    end

    -- Вычисляем альфа-канал для плавного появления и исчезновения
    local alpha = 255
    if elapsedTime < self.FadeTime then
        -- Фаза плавного появления
        alpha = Lerp(elapsedTime / self.FadeTime, 0, 255)
    elseif elapsedTime > (self.ShowAmmoDuration + self.FadeTime) then
        -- Фаза плавного исчезновения
        local fadeOutTime = elapsedTime - (self.ShowAmmoDuration + self.FadeTime)
        alpha = Lerp(fadeOutTime / self.FadeTime, 255, 0)
    else
        alpha = 255 -- Полностью видимый текст
    end

    if not IsValid(self:GetOwner()) then return end
    local owner = self:GetOwner()
    local boneIndex = owner:LookupBone("ValveBiped.Bip01_R_Hand")
    if not boneIndex then return end
    local bonePos, boneAng = owner:GetBonePosition(boneIndex)
    -- Настройка позиции текста относительно руки
    local offset = Vector(0, 10, -5)
    local textPos = bonePos + boneAng:Right() * offset.x + boneAng:Forward() * offset.y + boneAng:Up() * offset.z
    -- Настройка угла поворота текста
    local textAng = boneAng
    textAng:RotateAroundAxis(boneAng:Right(), 90)
    textAng:RotateAroundAxis(boneAng:Up(), 90)
    textAng:RotateAroundAxis(boneAng:Forward(), 0)
    -- Отрисовка 3D текста
    cam.Start3D2D(textPos, textAng, 0.1)
    draw.SimpleText("Патроны: " .. self:Clip1() .. "/" .. owner:GetAmmoCount(self.Primary.Ammo), "DermaLarge", 0, 0, Color(255, 255, 255, alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
    cam.End3D2D()
end

-- Удаление клиентской модели оружия
function SWEP:OnRemove()
    if IsValid(self.WeaponModel) then
        self.WeaponModel:Remove()
        self.WeaponModel = nil
    end
end

-- Очистка модели при холстере
function SWEP:Holster()
    if IsValid(self.WeaponModel) then
        self.WeaponModel:Remove()
        self.WeaponModel = nil
    end
    return true
end
```
Перечисли все проблемы, баги, ошибки в скриптах