Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

How to make the pistol this for FPS model not damage players but still damage NPCs?

Asked by 3 years ago
Edited 3 years ago

I've been trying to figure out a way to be able to make the pistol this for FPS Roblox pistol model not to do damage to players, but the script is too long and complicated for me to understand. Please help.

Thank you!

(pistol this for FPS script)

--------------------- TEMPLATE ASSAULT RIFLE WEAPON ---------------------------
-- Waits for the child of the specified parent
local function WaitForChild(parent, childName)
    while not parent:FindFirstChild(childName) do parent.ChildAdded:wait() end
    return parent[childName]
end

----- MAGIC NUMBERS ABOUT THE TOOL -----
-- How much damage a bullet does
local Damage = 50
-- How many times per second the gun can fire
local FireRate = 20 / 30
-- The maximum distance the can can shoot, this value should never go above 1000
local Range = 400
-- In radians the minimum accuracy penalty
local MinSpread = 0.01
-- In radian the maximum accuracy penalty
local MaxSpread = 0.1
-- Number of bullets in a clip
local ClipSize = 12
-- DefaultValue for spare ammo
local SpareAmmo = 100
-- The amount the aim will increase or decrease by
-- decreases this number reduces the speed that recoil takes effect
local AimInaccuracyStepAmount = 0.01
-- Time it takes to reload weapon
local ReloadTime = 2
----------------------------------------

-- Colors
local FriendlyReticleColor = Color3.new(0, 1, 0)
local EnemyReticleColor = Color3.new(1, 0, 0)
local NeutralReticleColor   = Color3.new(1, 1, 1)

local Spread = MinSpread
local AmmoInClip = ClipSize

local Tool = script.Parent
local Handle = WaitForChild(Tool, 'Handle')
local WeaponGui = nil

local LeftButtonDown
local Reloading = false
local IsShooting = false

-- Player specific convenience variables
local MyPlayer = nil
local MyCharacter = nil
local MyHumanoid = nil
local MyTorso = nil
local MyMouse = nil

local RecoilAnim
local RecoilTrack = nil

local IconURL = Tool.TextureId  -- URL to the weapon icon asset

local DebrisService = game:GetService('Debris')
local PlayersService = game:GetService('Players')


local FireSound

local OnFireConnection = nil
local OnReloadConnection = nil

local DecreasedAimLastShot = false
local LastSpreadUpdate = time()

-- this is a dummy object that holds the flash made when the gun is fired
local FlashHolder = nil


local WorldToCellFunction = Workspace.Terrain.WorldToCellPreferSolid
local GetCellFunction = Workspace.Terrain.GetCell

function RayIgnoreCheck(hit, pos)
    if hit then
        if hit.Transparency >= 1 or string.lower(hit.Name) == "water" or
            hit.Name == "Effect" or hit.Name == "Rocket" or hit.Name == "Bullet" or
            hit.Name == "Handle" or hit:IsDescendantOf(MyCharacter) then
            return true
        elseif hit:IsA('Terrain') and pos then
            local cellPos = WorldToCellFunction(Workspace.Terrain, pos)
            if cellPos then
                local cellMat = GetCellFunction(Workspace.Terrain, cellPos.x, cellPos.y, cellPos.z)
                if cellMat and cellMat == Enum.CellMaterial.Water then
                    return true
                end
            end
        end
    end
    return false
end

-- @preconditions: vec should be a unit vector, and 0 < rayLength <= 1000
function RayCast(startPos, vec, rayLength)
    local hitObject, hitPos = game.Workspace:FindPartOnRay(Ray.new(startPos + (vec * .01), vec * rayLength), Handle)
    if hitObject and hitPos then
        local distance = rayLength - (hitPos - startPos).magnitude
        if RayIgnoreCheck(hitObject, hitPos) and distance > 0 then
            -- there is a chance here for potential infinite recursion
            return RayCast(hitPos, vec, distance)
        end
    end
    return hitObject, hitPos
end



function TagHumanoid(humanoid, player)
    -- Add more tags here to customize what tags are available.
    while humanoid:FindFirstChild('creator') do
        humanoid:FindFirstChild('creator'):Destroy()
    end 
    local creatorTag = Instance.new("ObjectValue")
    creatorTag.Value = player
    creatorTag.Name = "creator"
    creatorTag.Parent = humanoid
    DebrisService:AddItem(creatorTag, 1.5)

    local weaponIconTag = Instance.new("StringValue")
    weaponIconTag.Value = IconURL
    weaponIconTag.Name = "icon"
    weaponIconTag.Parent = creatorTag
end

local function CreateFlash()
    if FlashHolder then
        local flash = Instance.new('Fire', FlashHolder)
        flash.Color = Color3.new(1, 140 / 255, 0)
        flash.SecondaryColor = Color3.new(1, 0, 0)
        flash.Size = 0.3
        DebrisService:AddItem(flash, FireRate / 1.5)
    else
        FlashHolder = Instance.new("Part", Tool)
        FlashHolder.Transparency = 1
        FlashHolder.CanCollide= false
        FlashHolder.Size = Vector3.new(1, 1, 1)
        FlashHolder.Position = Tool.Handle.Position
        local Weld = Instance.new("ManualWeld")
        Weld.C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1)
        Weld.C1 = CFrame.new(0, 2.2, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0)
        Weld.Part0 = FlashHolder
        Weld.Part1 = Tool.Handle
        Weld.Parent = FlashHolder
    end
end

local function CreateBullet(bulletPos)
    local bullet = Instance.new('Part', Workspace)
    bullet.FormFactor = Enum.FormFactor.Custom
    bullet.Size = Vector3.new(0.1, 0.1, 0.1)
    bullet.BrickColor = MyPlayer.TeamColor
    bullet.Shape = Enum.PartType.Ball
    bullet.CanCollide = false
    bullet.CFrame = CFrame.new(bulletPos)
    bullet.Anchored = true
    bullet.TopSurface = Enum.SurfaceType.Smooth
    bullet.BottomSurface = Enum.SurfaceType.Smooth
    bullet.Name = 'Bullet'
    DebrisService:AddItem(bullet, 2.5)
    local fire = Instance.new("Fire", bullet)
    fire.Color = Color3.new(MyPlayer.TeamColor.r, MyPlayer.TeamColor.g, MyPlayer.TeamColor.b)
    fire.SecondaryColor = Color3.new(MyPlayer.TeamColor.r, MyPlayer.TeamColor.g, MyPlayer.TeamColor.b)
    fire.Size = 5
    fire.Heat = 0
    DebrisService:AddItem(fire, 0.2)
    return bullet
end

local function Reload()
    if not Reloading then
        Reloading = true
        -- Don't reload if you are already full or have no extra ammo
        if AmmoInClip ~= ClipSize and SpareAmmo > 0 then
            if RecoilTrack then
                RecoilTrack:Stop()
            end
            if WeaponGui and WeaponGui:FindFirstChild('Crosshair') then
                if WeaponGui.Crosshair:FindFirstChild('ReloadingLabel') then
                    WeaponGui.Crosshair.ReloadingLabel.Visible = true
                end
            end
            wait(ReloadTime)
            -- Only use as much ammo as you have
            local ammoToUse = math.min(ClipSize - AmmoInClip, SpareAmmo)
            AmmoInClip = AmmoInClip + ammoToUse
            SpareAmmo = SpareAmmo - ammoToUse
            UpdateAmmo(AmmoInClip)
        end
        Reloading = false
    end
end

function OnFire()
    if IsShooting then return end
    if MyHumanoid and MyHumanoid.Health > 0 then
        if RecoilTrack and AmmoInClip > 0 then
            RecoilTrack:Play()
        end
        IsShooting = true
        while LeftButtonDown and AmmoInClip > 0 and not Reloading do
            if Spread and not DecreasedAimLastShot then
                Spread = math.min(MaxSpread, Spread + AimInaccuracyStepAmount)
                UpdateCrosshair(Spread)
            end
            DecreasedAimLastShot = not DecreasedAimLastShot
            if Handle:FindFirstChild('FireSound') then
                Handle.FireSound:Play()
            end
            CreateFlash()
            if MyMouse then
                local targetPoint = MyMouse.Hit.p
                local shootDirection = (targetPoint - Handle.Position).unit
                -- Adjust the shoot direction randomly off by a little bit to account for recoil
                shootDirection = CFrame.Angles((0.5 - math.random()) * 2 * Spread,
                    (0.5 - math.random()) * 2 * Spread,
                    (0.5 - math.random()) * 2 * Spread) * shootDirection
                local hitObject, bulletPos = RayCast(Handle.Position, shootDirection, Range)
                local bullet
                -- Create a bullet here
                if hitObject then
                    bullet = CreateBullet(bulletPos)
                end
                if hitObject and hitObject.Parent then
                    local hitHumanoid = hitObject.Parent:FindFirstChild("Humanoid")
                    if hitHumanoid then
                        local hitPlayer = game.Players:GetPlayerFromCharacter(hitHumanoid.Parent)
                        if MyPlayer.Neutral or (hitPlayer and hitPlayer.TeamColor ~= MyPlayer.TeamColor) then
                            TagHumanoid(hitHumanoid, MyPlayer)
                            hitHumanoid:TakeDamage(Damage)
                            if bullet then
                                bullet:Destroy()
                                bullet = nil
                                --bullet.Transparency = 1
                            end
                            Spawn(UpdateTargetHit)
                        end
                    end
                end

                AmmoInClip = AmmoInClip - 1
                UpdateAmmo(AmmoInClip)
            end
            wait(FireRate)
        end     
        IsShooting = false
        if AmmoInClip == 0 then
            Reload()
        end
        if RecoilTrack then
            RecoilTrack:Stop()
        end
    end
end

local TargetHits = 0
function UpdateTargetHit()
    TargetHits = TargetHits + 1
    if WeaponGui and WeaponGui:FindFirstChild('Crosshair') and WeaponGui.Crosshair:FindFirstChild('TargetHitImage') then
        WeaponGui.Crosshair.TargetHitImage.Visible = true
    end
    wait(0.5)
    TargetHits = TargetHits - 1
    if TargetHits == 0 and WeaponGui and WeaponGui:FindFirstChild('Crosshair') and WeaponGui.Crosshair:FindFirstChild('TargetHitImage') then
        WeaponGui.Crosshair.TargetHitImage.Visible = false
    end
end

function UpdateCrosshair(value, mouse)
    if WeaponGui then
        local absoluteY = 650
        WeaponGui.Crosshair:TweenSize(
            UDim2.new(0, value * absoluteY * 2 + 23, 0, value * absoluteY * 2 + 23),
            Enum.EasingDirection.Out,
            Enum.EasingStyle.Linear,
            0.33)
    end
end

-- Continued

2 answers

Log in to vote
0
Answered by
Speedmask 661 Moderation Voter
3 years ago
Edited 3 years ago

don't think you can't understand something because it's too long. remember that each section of the code only takes care of one particular task, so you can break it down in chunks. that said, I will try to help you identify the area of your code that you want to change. if you don't care and this is only for fun, skip to the end.

since you have the entire gun here, your code involves the recoil, the crosshair, the reload, etc. however, you don't care about any of that, and what you want is the damage mechanism.

thankfully, the creator of this gun named all of their functions correctly. you will find functions like Reload(), which are obviously useless to you, so you can skip it. in this way you can break down this large piece of code into something smaller. look for functions you think are important. for example, I read through the function CreateBullet(), but there was nothing about damage, so I skipped it. eventually you will find the function OnFire().

the way players are damaged in games is by changing the health of their Humanoid, this is an object that has health, speed, and other things you find in a player. most of the time, npcs will also have humanoids, if not some other type of health system.

for this reason, I'll look for the word "Humanoid", and there it is, on line 227. here is your relevant code:

local hitHumanoid = hitObject.Parent:FindFirstChild("Humanoid")
if hitHumanoid then
    local hitPlayer = game.Players:GetPlayerFromCharacter(hitHumanoid.Parent)
    if MyPlayer.Neutral or (hitPlayer and hitPlayer.TeamColor ~= MyPlayer.TeamColor) then
        TagHumanoid(hitHumanoid, MyPlayer)
        hitHumanoid:TakeDamage(Damage)
        if bullet then
            bullet:Destroy()
            bullet = nil
            --bullet.Transparency = 1
        end
        Spawn(UpdateTargetHit)
    end
end

it looks like this gun was only designed for killing players on the opposite team, not npcs. therefore, you can just delete that part. instead, just check if it was not a player, since npcs are the only humanoids that are not players. you can do this with the function GetPlayerFromCharacter(). if you get nothing, that means that the character did not have a player, so it wasn't one.

change lines 227-240 to this

local hitHumanoid = hitObject.Parent:FindFirstChild("Humanoid")
if hitHumanoid and not game.Players:GetPlayerFromCharacter(hitHumanoid.Parent) then
    hitHumanoid:TakeDamage(Damage)
    if bullet then
        bullet:Destroy()
        bullet = nil
        --bullet.Transparency = 1
    end
    Spawn(UpdateTargetHit)
end
0
I changed the part of the script you were talking about to this: ---- TEMPLATE ASSAULT RIFLE WEAPON ---- -- Waits for the child of the specified parent local function WaitForChild(parent, childName) while not parent:FindFirstChild(childName) do parent.ChildAdded:wait() end return parent[childName] end ----- MAGIC NUMBERS But now the gun doesn't shoot. MrSarp_shoot 37 — 3y
0
sorry, I'm not sure I followed your comment. did you change "local Damage = 50" to "local Damage = 0"? I'd assume that's all you need to do. Speedmask 661 — 3y
0
oh sorry, I meant if the gun did not damage players but still damaged NPCs, sorry about not making the title clear. MrSarp_shoot 37 — 3y
0
Tysm it works! I realised how much I was overthinking it. MrSarp_shoot 37 — 3y
Ad
Log in to vote
0
Answered by 3 years ago
-- Continued

function UpdateAmmo(value)
    if WeaponGui and WeaponGui:FindFirstChild('AmmoHud') and WeaponGui.AmmoHud:FindFirstChild('ClipAmmo') then
        WeaponGui.AmmoHud.ClipAmmo.Text = AmmoInClip
        if value > 0 and WeaponGui:FindFirstChild('Crosshair') and WeaponGui.Crosshair:FindFirstChild('ReloadingLabel') then
            WeaponGui.Crosshair.ReloadingLabel.Visible = false
        end
    end
    if WeaponGui and WeaponGui:FindFirstChild('AmmoHud') and WeaponGui.AmmoHud:FindFirstChild('TotalAmmo') then
        WeaponGui.AmmoHud.TotalAmmo.Text = SpareAmmo
    end
end


function OnMouseDown()
    LeftButtonDown = true
    OnFire()
end

function OnMouseUp()
    LeftButtonDown = false
end

function OnKeyDown(key)
    if string.lower(key) == 'r' then
        Reload()
    end
end


function OnEquipped(mouse)
    RecoilAnim = WaitForChild(Tool, 'Recoil')
    FireSound  = WaitForChild(Handle, 'FireSound')

    MyCharacter = Tool.Parent
    MyPlayer = game:GetService('Players'):GetPlayerFromCharacter(MyCharacter)
    MyHumanoid = MyCharacter:FindFirstChild('Humanoid')
    MyTorso = MyCharacter:FindFirstChild('Torso')
    MyMouse = mouse
    WeaponGui = WaitForChild(Tool, 'WeaponHud'):Clone()
    if WeaponGui and MyPlayer then
        WeaponGui.Parent = MyPlayer.PlayerGui
        UpdateAmmo(AmmoInClip)
    end
    if RecoilAnim then
        RecoilTrack = MyHumanoid:LoadAnimation(RecoilAnim)
    end

    if MyMouse then
        -- Disable mouse icon
        MyMouse.Icon = "rbxasset://textures\\GunCursor.png"
        MyMouse.Button1Down:connect(OnMouseDown)
        MyMouse.Button1Up:connect(OnMouseUp)
        MyMouse.KeyDown:connect(OnKeyDown)
    end
end


-- Unequip logic here
function OnUnequipped()
    LeftButtonDown = false
    Reloading = false
    MyCharacter = nil
    MyHumanoid = nil
    MyTorso = nil
    MyPlayer = nil
    MyMouse = nil
    if OnFireConnection then
        OnFireConnection:disconnect()
    end
    if OnReloadConnection then
        OnReloadConnection:disconnect()
    end
    if FlashHolder then
        FlashHolder = nil
    end
    if WeaponGui then
        WeaponGui.Parent = nil
        WeaponGui = nil
    end
    if RecoilTrack then
        RecoilTrack:Stop()
    end
end

local function SetReticleColor(color)
    if WeaponGui and WeaponGui:FindFirstChild('Crosshair') then
        for _, line in pairs(WeaponGui.Crosshair:GetChildren()) do
            if line:IsA('Frame') then
                line.BorderColor3 = color
            end
        end
    end
end


Tool.Equipped:connect(OnEquipped)
Tool.Unequipped:connect(OnUnequipped)

while true do
    wait(0.033)
    if WeaponGui and WeaponGui:FindFirstChild('Crosshair') and MyMouse then
        WeaponGui.Crosshair.Position = UDim2.new(0, MyMouse.X, 0, MyMouse.Y)
        SetReticleColor(NeutralReticleColor)

        local target = MyMouse.Target
        if target and target.Parent then
            local player = PlayersService:GetPlayerFromCharacter(target.Parent)
            if player then
                if MyPlayer.Neutral or player.TeamColor ~= MyPlayer.TeamColor then
                    SetReticleColor(EnemyReticleColor)
                else
                    SetReticleColor(FriendlyReticleColor)
                end
            end
        end
    end
    if Spread and not IsShooting then
        local currTime = time()
        if currTime - LastSpreadUpdate > FireRate * 2 then
            LastSpreadUpdate = currTime
            Spread = math.max(MinSpread, Spread - AimInaccuracyStepAmount)
            UpdateCrosshair(Spread, MyMouse)
        end
    end
end

Answer this question