Universal script for weapons
Key RequiredUniversal

Universal script for weapons

Universal ScriptCOOlInkKidCOOlInkKid 995 views 116 executesUpdated Jan 25, 2026
Unrated
00
Lua Script•278 lines (6981 chars)
-- main module
-- by COOlInkKid 
-- universal script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")

-- Weapons module
local WeaponModule = {}
WeaponModule.__index = WeaponModule

-- Configuration
local WEAPON_CONFIGS = {
    ["AssaultRifle"] = {
        Damage = 25,
        FireRate = 0.15, -- секунд между выстрелами
        MagazineSize = 30,
        ReloadTime = 2.5,
        MaxAmmo = 180,
        Spread = 3, -- градусы
        Range = 500
    },
    ["Pistol"] = {
        Damage = 35,
        FireRate = 0.4,
        MagazineSize = 12,
        ReloadTime = 1.8,
        MaxAmmo = 60,
        Spread = 2,
        Range = 300
    }
}

function WeaponModule.new(weaponType, owner)
    local self = setmetatable({}, WeaponModule)
    
    self.WeaponType = weaponType
    self.Owner = owner
    self.Config = WEAPON_CONFIGS[weaponType] or WEAPON_CONFIGS["AssaultRifle"]
    
    -- Unknown
    self.CurrentAmmo = self.Config.MagazineSize
    self.TotalAmmo = self.Config.MaxAmmo
    self.IsReloading = false
    self.CanFire = true
    self.Equipped = false
    
    return self
end

function WeaponModule:Fire(mousePosition)
    if not self.CanFire or self.IsReloading or self.CurrentAmmo <= 0 then
        return
    end
    
    self.CanFire = false
    self.CurrentAmmo -= 1
    
    -- visual effects
    self:PlayFireEffects()
    
    -- Logic hit
    local hitResult = self:CalculateHit(mousePosition)
    if hitResult and hitResult.Instance then
        self:ProcessHit(hitResult)
    end
    
    -- sound fire
    self:PlaySound("Fire")
    
    -- Automatic reload
    if self.CurrentAmmo <= 0 then
        self:StartReload()
    else
        -- fireRate wait
        task.wait(self.Config.FireRate)
        self.CanFire = true
    end
end

function WeaponModule:CalculateHit(mousePosition)
    local character = self.Owner.Character
    if not character then return end
    
    local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
    if not humanoidRootPart then return end
    
    -- spread
    local spread = math.rad(self.Config.Spread)
    local direction = (mousePosition - humanoidRootPart.Position).Unit
    direction = direction + Vector3.new(
        (math.random() - 0.5) * spread,
        (math.random() - 0.5) * spread,
        (math.random() - 0.5) * spread
    )
    
    -- result raycast
    local raycastParams = RaycastParams.new()
    raycastParams.FilterDescendantsInstances = {character}
    raycastParams.FilterType = Enum.RaycastFilterType.Exclude
    
    local raycastResult = workspace:Raycast(
        humanoidRootPart.Position,
        direction * self.Config.Range,
        raycastParams
    )
    
    return raycastResult
end

function WeaponModule:ProcessHit(hitResult)
    local hitPart = hitResult.Instance
    local humanoid = hitPart.Parent:FindFirstChildOfClass("Humanoid")
    
    if humanoid then
        -- damage
        humanoid:TakeDamage(self.Config.Damage)
        
        -- effects
        self:CreateHitEffect(hitResult.Position)
        
        -- unknown
        self:ShowHitMarker()
    end
end

function WeaponModule:StartReload()
    if self.IsReloading or self.CurrentAmmo == self.Config.MagazineSize then
        return
    end
    
    local ammoNeeded = self.Config.MagazineSize - self.CurrentAmmo
    if self.TotalAmmo <= 0 or ammoNeeded <= 0 then
        return
    end
    
    self.IsReloading = true
    self.CanFire = false
    
    -- sounds reload
    self:PlaySound("Reload")
    
    -- Visualisation 
    self:ShowReloadIndicator()
    
    task.wait(self.Config.ReloadTime)
    
    -- unknown
    local ammoToReload = math.min(ammoNeeded, self.TotalAmmo)
    self.CurrentAmmo += ammoToReload
    self.TotalAmmo -= ammoToReload
    
    self.IsReloading = false
    self.CanFire = true
    
    -- Update UI
    self:UpdateAmmoUI()
end

function WeaponModule:PlayFireEffects()
    -- logic effects
    -- Мuzzle flash, trassers
end

function WeaponModule:CreateHitEffect(position)
    local hitEffect = Instance.new("Part")
    hitEffect.Size = Vector3.new(0.2, 0.2, 0.2)
    hitEffect.Position = position
    hitEffect.Material = Enum.Material.Neon
    hitEffect.Color = Color3.fromRGB(255, 50, 50)
    hitEffect.Anchored = true
    hitEffect.CanCollide = false
    hitEffect.Parent = workspace
    
    game.Debris:AddItem(hitEffect, 0.5)
end

function WeaponModule:ShowHitMarker()
    -- logic update UI
end

function WeaponModule:ShowReloadIndicator()
    -- logic indicators 
end

function WeaponModule:UpdateAmmoUI()
    -- update system
end

function WeaponModule:PlaySound(soundType)
    -- sound logic 
end

-- Control system weapons 
local WeaponController = {}
WeaponController.__index = WeaponController

function WeaponController.new(player)
    local self = setmetatable({}, WeaponController)
    
    self.Player = player
    self.CurrentWeapon = nil
    self.Weapons = {}
    
    self:SetupInput()
    
    return self
end

function WeaponController:SetupInput()
    local playerGui = self.Player:WaitForChild("PlayerGui")
    
    UserInputService.InputBegan:Connect(function(input, gameProcessed)
        if gameProcessed then return end
        
        if input.UserInputType == Enum.UserInputType.MouseButton1 then
            self:OnMouseClick()
        elseif input.KeyCode == Enum.KeyCode.R then
            self:OnReloadKey()
        elseif input.KeyCode == Enum.KeyCode.One then
            self:SwitchWeapon("AssaultRifle")
        elseif input.KeyCode == Enum.KeyCode.Two then
            self:SwitchWeapon("Pistol")
        end
    end)
end

function WeaponController:OnMouseClick()
    if self.CurrentWeapon then
        local mouse = self.Player:GetMouse()
        self.CurrentWeapon:Fire(mouse.Hit.Position)
    end
end

function WeaponController:OnReloadKey()
    if self.CurrentWeapon then
        self.CurrentWeapon:StartReload()
    end
end

function WeaponController:SwitchWeapon(weaponType)
    if self.Weapons[weaponType] then
        self.CurrentWeapon = self.Weapons[weaponType]
        self:UpdateWeaponUI()
    else
        self:AddWeapon(weaponType)
    end
end

function WeaponController:AddWeapon(weaponType)
    local newWeapon = WeaponModule.new(weaponType, self.Player)
    self.Weapons[weaponType] = newWeapon
    self.CurrentWeapon = newWeapon
    self:UpdateWeaponUI()
end

function WeaponController:UpdateWeaponUI()
    -- update weapons system
end

-- Initialisation system 
local function onPlayerAdded(player)
    local controller = WeaponController.new(player)
    
    -- unknown
    task.wait(1)
    controller:AddWeapon("AssaultRifle")
    controller:AddWeapon("Pistol")
end

-- unknown
Players.PlayerAdded:Connect(onPlayerAdded)
for _, player in ipairs(Players:GetPlayers()) do
    task.spawn(onPlayerAdded, player)
end

return WeaponModule

Features & Information

Universal script Weapons module Sound module Weapon configuration And more

Community Comments (1)

COOlInkKidCOOlInkKidJan 25, 2026

Warning! I haven't tested it and don't know if it works at all.

More Scripts for Universal Scripts