Jump to content

weapon attachment mode


Recommended Posts

hello ive been trying to make a weapon attachment mode for mta sa 
problems that ive encountred
the silencer does not silence (lol)
flashlight illuminates the player not infront of him
the attachments stay stuck to the player even when switching weapons until i remove them from the menu https://ibb.co/q3CgPG7d
and the laser works fine dont worry lol
can you help me ?
heres the client, server and meta

-- Client-side weapon attachments management

local screenW, screenH = guiGetScreenSize()
local ATTACHMENT_MODELS = {
    silencer = 348,
    flashlight = 349,
    laser = 350
}
 
-- Sound ranges for different weapons when suppressed
local SOUND_RANGES = {
    [22] = { suppressed = 20 },  -- Pistol
    [23] = { suppressed = 25 },  -- Silenced Pistol
    [24] = { suppressed = 30 },  -- Desert Eagle
    [25] = { suppressed = 35 },  -- Shotgun
    [29] = { suppressed = 40 },  -- MP5
    [30] = { suppressed = 45 },  -- AK-47
    [31] = { suppressed = 45 }   -- M4
}
 
-- Track active attachments and effects
local activeAttachments = {}
local activeEffects = {}
 
-- GUI elements
local gui = {
    window = nil,
    buttons = {}
}
 
-- Attachment positions and rotations
local attachmentConfig = {
    silencer = {
        pos = {x = 0.2, y = 0, z = 0.02},
        rot = {x = 0, y = 90, z = 0},
        scale = {x = 1.0, y = 1.0, z = 1.0}
    },
    flashlight = {
        pos = {x = 0.15, y = 0.05, z = 0.02},
        rot = {x = 0, y = 90, z = 0},
        scale = {x = 0.8, y = 0.8, z = 0.8}
    },
    laser = {
        pos = {x = 0.15, y = -0.05, z = 0.02},
        rot = {x = 0, y = 90, z = 0},
        scale = {x = 0.8, y = 0.8, z = 0.8}
    }
}
 
-- Create attachment menu
function createAttachmentMenu()
    if gui.window then destroyElement(gui.window) end
   
    gui.window = guiCreateWindow(screenW/2-150, screenH/2-200, 300, 400, "Weapon Attachments", false)
   
    local y = 30
    for _, attachment in ipairs({"silencer", "flashlight", "laser"}) do
        -- Attach button
        gui.buttons[attachment.."_attach"] = guiCreateButton(10, y, 135, 30, "Attach "..attachment, false, gui.window)
        addEventHandler("onClientGUIClick", gui.buttons[attachment.."_attach"], function()
            triggerServerEvent("onRequestAttachment", localPlayer, attachment)
        end, false)
       
        -- Remove button
        gui.buttons[attachment.."_remove"] = guiCreateButton(155, y, 135, 30, "Remove "..attachment, false, gui.window)
        addEventHandler("onClientGUIClick", gui.buttons[attachment.."_remove"], function()
            triggerServerEvent("onRequestRemoveAttachment", localPlayer, attachment)
        end, false)
       
        y = y + 40
    end
   
    -- Close button
    local closeButton = guiCreateButton(10, 360, 280, 30, "Close", false, gui.window)
    addEventHandler("onClientGUIClick", closeButton, function()
        destroyElement(gui.window)
        gui.window = nil
    end, false)
   
    showCursor(true)
end
 
-- Handle attachment updates
addEvent("onAttachmentUpdate", true)
addEventHandler("onAttachmentUpdate", root, function(player, attachmentType, attached)
    if attached then
        createAttachment(player, attachmentType)
    else
        removeAttachment(player, attachmentType)
    end
end)
 
-- Handle silenced weapon fire
addEvent("onSilencedWeaponFire", true)
addEventHandler("onSilencedWeaponFire", root, function(x, y, z, weaponId)
    -- Play suppressed shot sound
    local sound = playSound3D("files/silenced_shot.wav", x, y, z)
    if sound then
        -- Calculate volume based on distance
        local px, py, pz = getElementPosition(localPlayer)
        local distance = getDistanceBetweenPoints3D(x, y, z, px, py, pz)
        local maxRange = SOUND_RANGES[weaponId].suppressed
        local volume = 1 - (distance / maxRange)
        setSoundVolume(sound, math.max(0.1, volume))
        setSoundMaxDistance(sound, maxRange)
    end
   
    -- Create subtle muzzle flash effect
    local effect = createEffect("gunflash", x, y, z)
    if effect then
        setEffectSpeed(effect, 0.5) -- Reduce the effect intensity
        setTimer(destroyElement, 50, 1, effect)
    end
end)
 
-- Handle weapon switch for silenced weapons
addEventHandler("onClientPlayerWeaponSwitch", root, function(prevSlot, newSlot)
    if source == localPlayer then
        local weaponId = getPedWeapon(localPlayer, newSlot)
        if activeAttachments[localPlayer] and activeAttachments[localPlayer].silencer then
            -- Update weapon properties for silenced weapon
            local x, y, z = getElementPosition(localPlayer)
            triggerServerEvent("onPlayerSilencedWeaponSwitch", localPlayer, weaponId)
        end
    end
end)
 
-- Create physical attachment
function createAttachment(player, attachmentType)
    if not isElement(player) then return end
   
    -- Remove existing attachment
    removeAttachment(player, attachmentType)
   
    -- Create attachment object
    local obj = createObject(ATTACHMENT_MODELS[attachmentType], 0, 0, 0)
    if not obj then return end
   
    -- Configure attachment
    local config = attachmentConfig[attachmentType]
    setObjectScale(obj, config.scale.x, config.scale.y, config.scale.z)
   
    -- Attach to weapon
    exports.bone_attach:attachElementToBone(obj, player, 12,
        config.pos.x, config.pos.y, config.pos.z,
        config.rot.x, config.rot.y, config.rot.z
    )
   
    -- Store attachment
    if not activeAttachments[player] then activeAttachments[player] = {} end
    activeAttachments[player][attachmentType] = obj
   
    -- Create effects
    if attachmentType == "flashlight" then
        createFlashlightEffect(player)
    elseif attachmentType == "laser" then
        createLaserEffect(player)
    end
end
 
-- Create flashlight effect
function createFlashlightEffect(player)
    if not activeAttachments[player] or not activeAttachments[player].flashlight then return end
   
    local function updateLight()
        if not isElement(player) or not activeAttachments[player] or not activeAttachments[player].flashlight then
            removeEventHandler("onClientRender", root, updateLight)
            return
        end
       
        local weaponSlot = getPedWeaponSlot(player)
        if weaponSlot < 2 or weaponSlot > 7 then return end
       
        local x, y, z = getPedWeaponMuzzlePosition(player)
        local tx, ty, tz = getPedTargetEnd(player)
       
        -- Create light effect
        local light = createLight(0, x, y, z, 10, 255, 255, 255)
        setLightDirection(light, tx-x, ty-y, tz-z)
       
        -- Clean up previous frame's light
        setTimer(function() if isElement(light) then destroyElement(light) end end, 50, 1)
    end
   
    addEventHandler("onClientRender", root, updateLight)
end
 
-- Create laser effect
function createLaserEffect(player)
    if not activeAttachments[player] or not activeAttachments[player].laser then return end
   
    local function updateLaser()
        if not isElement(player) or not activeAttachments[player] or not activeAttachments[player].laser then
            removeEventHandler("onClientRender", root, updateLaser)
            return
        end
       
        local weaponSlot = getPedWeaponSlot(player)
        if weaponSlot < 2 or weaponSlot > 7 then return end
       
        local x, y, z = getPedWeaponMuzzlePosition(player)
        local tx, ty, tz = getPedTargetEnd(player)
       
        -- Draw laser line
        dxDrawLine3D(x, y, z, tx, ty, tz, tocolor(255, 0, 0, 150), 1)
    end
   
    addEventHandler("onClientRender", root, updateLaser)
end
 
-- Remove attachment
function removeAttachment(player, attachmentType)
    if not activeAttachments[player] or not activeAttachments[player][attachmentType] then return end
   
    if isElement(activeAttachments[player][attachmentType]) then
        destroyElement(activeAttachments[player][attachmentType])
    end
   
    activeAttachments[player][attachmentType] = nil
end
 
-- Command to open menu
addCommandHandler("attachments", createAttachmentMenu)
 
-- Clean up on player quit
addEventHandler("onClientPlayerQuit", root, function()
    if activeAttachments[source] then
        for attachmentType, _ in pairs(activeAttachments[source]) do
            removeAttachment(source, attachmentType)
        end
        activeAttachments[source] = nil
    end
end)


server code
 
-- Server-side weapon attachments management

-- Constants
local WEAPON_IDS = {
    PISTOL_9MM = 22,
    SILENCED_PISTOL = 23,
    MP5 = 29,
    AK47 = 30,
    M4 = 31,
    SNIPER = 34
}
 
-- Sound range configurations
local SOUND_RANGES = {
    [WEAPON_IDS.PISTOL_9MM] = { normal = 100, suppressed = 20 },
    [WEAPON_IDS.MP5] = { normal = 120, suppressed = 25 },
    [WEAPON_IDS.AK47] = { normal = 150, suppressed = 30 },
    [WEAPON_IDS.M4] = { normal = 150, suppressed = 30 },
    [WEAPON_IDS.SNIPER] = { normal = 200, suppressed = 40 }
}
 
-- Track player attachments and weapon states
local playerAttachments = {}
local silencedWeapons = {}
 
-- Initialize player data
addEventHandler("onPlayerJoin", root, function()
    playerAttachments[source] = {}
    silencedWeapons[source] = {}
end)
 
-- Cleanup on quit
addEventHandler("onPlayerQuit", root, function()
    playerAttachments[source] = nil
    silencedWeapons[source] = nil
end)
 
-- Handle silenced weapon fire
addEventHandler("onPlayerWeaponFire", root, function(weapon)
    if silencedWeapons[source] and silencedWeapons[source][weapon] then
        local x, y, z = getElementPosition(source)
       
        -- Get nearby players
        local nearbyPlayers = getElementsWithinRange(x, y, z, SOUND_RANGES[weapon].normal, "player")
       
        -- Handle silenced shot effects
        for _, player in ipairs(nearbyPlayers) do
            if player ~= source then
                local px, py, pz = getElementPosition(player)
                local distance = getDistanceBetweenPoints3D(x, y, z, px, py, pz)
               
                if distance <= SOUND_RANGES[weapon].suppressed then
                    triggerClientEvent(player, "onSilencedWeaponFire", source, x, y, z, weapon)
                end
            end
        end
    end
end)
 
-- Handle attachment requests
addEvent("onRequestAttachment", true)
addEventHandler("onRequestAttachment", root, function(attachmentType)
    local weaponId = getPedWeapon(client)
   
    if not isWeaponCompatible(weaponId, attachmentType) then
        outputChatBox("This attachment is not compatible with your weapon.", client, 255, 0, 0)
        return
    end
   
    if not playerAttachments[client] then
        playerAttachments[client] = {}
    end
   
    -- Remove existing attachment if present
    if playerAttachments[client][attachmentType] then
        removeAttachment(client, attachmentType)
    end
   
    -- Apply new attachment
    playerAttachments[client][attachmentType] = true
   
    -- Special handling for silencer
    if attachmentType == "silencer" then
        if not silencedWeapons[client] then
            silencedWeapons[client] = {}
        end
        silencedWeapons[client][weaponId] = true
       
        -- Apply silencer properties
        setWeaponProperty(weaponId, "pro", "weapon_range", SOUND_RANGES[weaponId].suppressed)
        setWeaponProperty(weaponId, "pro", "flags_aim", true)
        setWeaponProperty(weaponId, "std", "fire_rotation", 0.0)
    end
   
    triggerClientEvent(root, "onAttachmentUpdate", client, client, attachmentType, true, weaponId)
end)
 
-- Handle attachment removal
addEvent("onRequestRemoveAttachment", true)
addEventHandler("onRequestRemoveAttachment", root, function(attachmentType)
    if removeAttachment(client, attachmentType) then
        outputChatBox("Attachment removed successfully.", client, 0, 255, 0)
    end
end)
 
-- Remove attachment function
function removeAttachment(player, attachmentType)
    if not playerAttachments[player] or not playerAttachments[player][attachmentType] then
        return false
    end
   
    local weaponId = getPedWeapon(player)
   
    if attachmentType == "silencer" and silencedWeapons[player] then
        silencedWeapons[player][weaponId] = nil
       
        -- Reset weapon properties
        setWeaponProperty(weaponId, "pro", "weapon_range", SOUND_RANGES[weaponId].normal)
        setWeaponProperty(weaponId, "pro", "flags_aim", false)
        setWeaponProperty(weaponId, "pro", "maximum_clip_ammo", 17)
        setWeaponProperty(weaponId, "std", "fire_rotation", 1.0)
    end
   
    playerAttachments[player][attachmentType] = nil
    triggerClientEvent(root, "onAttachmentUpdate", player, player, attachmentType, false, weaponId)
   
    return true
end
 
-- Utility function for weapon compatibility
function isWeaponCompatible(weaponId, attachmentType)
    local compatibleWeapons = {
        silencer = {
            [WEAPON_IDS.PISTOL_9MM] = true,
            [WEAPON_IDS.MP5] = true,
            [WEAPON_IDS.M4] = true
        },
        flashlight = {
            [WEAPON_IDS.PISTOL_9MM] = true,
            [WEAPON_IDS.MP5] = true,
            [WEAPON_IDS.AK47] = true,
            [WEAPON_IDS.M4] = true,
            [WEAPON_IDS.SNIPER] = true
        },
        laser = {
            [WEAPON_IDS.PISTOL_9MM] = true,
            [WEAPON_IDS.MP5] = true,
            [WEAPON_IDS.AK47] = true,
            [WEAPON_IDS.M4] = true,
            [WEAPON_IDS.SNIPER] = true
        }
    }
   
    return compatibleWeapons[attachmentType] and compatibleWeapons[attachmentType][weaponId]
end

 
heres the meta 
 
<meta>
<info author="Weapon Attachments System" version="1.0.0" type="script"/>
<!-- Client Scripts -->
<script src="attachmentc.lua" type="client" cache="false"/>
<!-- Server Scripts -->
<script src="attachments.lua" type="server"/>
<!-- Files -->
<file src="files/silenced_shot.wav"/>
<file src="files/flashlight.png"/>
<file src="files/laser.png"/>
<!-- Required Resources -->
<include resource="bone_attach"/>
<!-- Exports -->
<export function="attachWeaponMod" type="server"/>
<export function="removeWeaponMod" type="server"/>
</meta>
 
Edited by RoddyDaBaddy
wrong format sorry
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...