```lua
-- weapon_p228.lua

if SERVER then
    AddCSLuaFile()
end

if CLIENT then
    SWEP.PrintName = "P228"
    SWEP.Author = "Ваше Имя"
    SWEP.Slot = 1
    SWEP.SlotPos = 1
    SWEP.DrawAmmo = true
    SWEP.DrawCrosshair = true
    SWEP.ViewModelFOV = 60
    SWEP.ViewModelFlip = true -- Попробуйте установить true, если оружие держится в левой руке
end

SWEP.Category = "Custom Weapons"

-- Модели
SWEP.ViewModel = "models/weapons/v_pist_p228.mdl"    -- Ваша модель вида от первого лица
SWEP.WorldModel = "models/weapons/w_pist_p228.mdl"   -- Ваша модель вида от третьего лица
SWEP.UseHands = true                                  -- Использовать стандартные руки GMod

SWEP.HoldType = "pistol"

-- Настройки Primary (Основное оружие)
SWEP.Primary.ClipSize = 12
SWEP.Primary.DefaultClip = 12
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = "Pistol"

-- Настройки Secondary (Вторичное оружие)
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"

-- Физика оружия на земле
SWEP.Weight = 5
SWEP.AutoSwitchTo = false
SWEP.AutoSwitchFrom = false

-- Инициализация SWEP
function SWEP:Initialize()
    self:SetHoldType(self.HoldType)

    if CLIENT then
        -- Убедитесь, что оружие держится в правильной руке
        self:SetWeaponHoldType("pistol")
    end
end

-- Первичное действие (стрельба)
function SWEP:PrimaryAttack()
    if not self:CanPrimaryAttack() then return end

    local owner = self:GetOwner()

    -- Воспроизвести звук выстрела
    self:EmitSound("Weapon_p228.Single")

    -- Воспроизвести анимацию выстрела
    self:SendWeaponAnim(ACT_VM_PRIMARYATTACK)

    -- Добавить отдачу (вида от первого лица)
    owner:ViewPunch(Angle(math.Rand(-0.2, -0.1), math.Rand(-0.1, 0.1), 0))

    -- Добавить эффект выстрела (например, гильзы)
    if CLIENT then
        self:EmitShell()
    else
        -- Серверная часть для эмуляции выстрела (можно добавить дополнительные эффекты здесь)
    end

    -- Создать выстрел
    self:ShootBullet(25, 1, 0.02)

    -- Потратить один патрон
    self:TakePrimaryAmmo(1)

    -- Установить время до следующего выстрела
    self:SetNextPrimaryFire(CurTime() + 0.3)
end

-- Функция создания выстрела
function SWEP:ShootBullet(damage, num_bullets, aimcone)
    local owner = self:GetOwner()
    if not IsValid(owner) then return end

    owner:LagCompensation(true)

    local bullet = {}
    bullet.Num    = num_bullets
    bullet.Src    = owner:GetShootPos()
    bullet.Dir    = owner:GetAimVector()
    bullet.Spread = Vector(aimcone, aimcone, 0)
    bullet.Tracer = 1
    bullet.Force  = damage * 2
    bullet.Damage = damage

    owner:FireBullets(bullet)

    owner:LagCompensation(false)
end

-- Функция для эмуляции вылета гильз
function SWEP:EmitShell()
    local shell = ents.Create("prop_physics")
    if not IsValid(shell) then return end

    shell:SetModel("models/shells/shell_9mm.mdl") -- Убедитесь, что модель гильзы существует
    shell:SetPos(self:GetMuzzlePosition())
    shell:SetAngles(self:GetOwner():GetAngles())
    shell:Spawn()
    shell:PhysWake()

    local phys = shell:GetPhysicsObject()
    if IsValid(phys) then
        local velocity = self:GetOwner():GetAimVector() * 100 + Vector(math.random(-50,50), math.random(-50,50), math.random(100,200))
        phys:SetVelocity(velocity)
    end

    -- Удалить гильзу через 10 секунд, чтобы не нагружать сервер
    SafeRemoveEntityDelayed(shell, 10)
end

-- Функция получения позиции дула оружия
function SWEP:GetMuzzlePosition()
    if not IsValid(self:GetOwner()) then return self:GetPos() end
    local vm = self:GetOwner():GetViewModel()
    if not IsValid(vm) then return self:GetPos() end
    local muzzle = vm:LookupAttachment("muzzle") -- Убедитесь, что ваша модель имеет attachment "muzzle"
    if muzzle == 0 then return vm:GetPos() end
    local attachment = vm:GetAttachment(muzzle)
    if not attachment then return vm:GetPos() end
    return attachment.Pos
end

-- Вторичное действие (можно реализовать прицеливание)
function SWEP:SecondaryAttack()
    -- Реализуйте прицеливание или другое действие
end

-- Перезарядка
function SWEP:Reload()
    local owner = self:GetOwner()
    if owner:GetAmmoCount(self.Primary.Ammo) <= 0 then return end
    self:DefaultReload(ACT_VM_RELOAD)
    self:SetNextPrimaryFire(CurTime() + 1)
end
```
Улучши свеп, сделай анимацию опускания оружия вниз при беге, сделай улучшенную отдачу и т.д. Сделай рефакторинг и структурируй код, оптимизируй его, добавь дополнения улучшающие SWEP