Local script:
local contextActionService = game:GetService("ContextActionService")
local replicatedStorage = game:GetService("ReplicatedStorage")
local runService = game:GetService("RunService")
local armWeaponsFolder = replicatedStorage:WaitForChild("FirstPersonWeapons")
local armTool = armWeaponsFolder:WaitForChild("Pistol"):Clone()
local flashPart = armTool:WaitForChild("GunFlash")
local armsBarrelAttachment = armTool:WaitForChild("Handle"):WaitForChild("BarrelAttachment")
local flashGui = flashPart:WaitForChild("MuzzleFlash")
local armsEquipAnim = armTool:WaitForChild("PistolEquip")
local armsHolsterAnim = armTool:WaitForChild("PistolHolster")
local armsShootAnim = armTool:WaitForChild("PistolShoot")
local armsReloadANim = armTool:WaitForChild("PistolReload")
local armsReloadSound = armTool:WaitForChild("ReloadSound")
local armsShootSound = armTool:WaitForChild("ShootSound")
local Tool = script.Parent
local ShootEvent = Tool:WaitForChild("RemoteShoot")
local ReloadEvent = Tool:WaitForChild("RemoteReload")
local Handle = Tool:WaitForChild("Handle")
local GunFlash = Tool:WaitForChild("GunFlash")
local MuzzleFlash = GunFlash:WaitForChild("MuzzleFlash")
local EquipSound = Handle:WaitForChild("EquipSound2")
local UnequipSound = Handle:WaitForChild("UnequipSound")
local serverShootSound = Handle:WaitForChild("ShootSound")
local serverReloadSound = Handle:WaitForChild("ReloadSound")
serverShootSound.Volume = 0
serverReloadSound.Volume = 0
local player = game.Players.LocalPlayer
MuzzleFlash.PlayerToHideFrom = player
local mouse = player:GetMouse()
local camera = workspace.CurrentCamera
local fpsArms: Model = camera:WaitForChild("FirstPersonArms")
local fpsHum = fpsArms:FindFirstChildOfClass("Humanoid")
local fpsRightArm: BasePart = fpsArms:WaitForChild("Right Arm")
local ToolAttach: Motor6D = fpsRightArm:WaitForChild("ToolAttach")
local armTracks = {
equip = fpsHum:LoadAnimation(armsEquipAnim),
holster = fpsHum:LoadAnimation(armsHolsterAnim),
shoot = fpsHum:LoadAnimation(armsShootAnim),
reload = fpsHum:LoadAnimation(armsReloadANim)
}
local ReloadActionName = "Pistol_Reload"
Handle.Transparency = 1
local isEquipped = false
local mouseHeldDown = false
local runDebounce = false
local runCd = 0.1
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
local function reload()
ReloadEvent:FireServer()
end
local function getAllCharactersInTeam(team: Team): {Model}
local characters = {}
for _, plr: Player in pairs(team:GetPlayers()) do
if plr.Character then
table.insert(characters, plr.Character)
end
end
return characters
end
local function getEverything(char: Model)
local everything = {}
for _, basepart: BasePart in pairs(char:GetDescendants()) do
if basepart:IsA("BasePart") then
table.insert(everything, basepart)
end
end
return everything
end
local function intoTable(result: RaycastResult)
local conversion = {}
conversion.Position = result.Position
conversion.Instance = result.Instance
conversion.Material = result.Material
conversion.Distance = result.Distance
conversion.Normal = result.Normal
return conversion
end
local function shoot()
params.FilterDescendantsInstances = {Tool.Parent, table.unpack(getEverything(Tool.Parent)), camera, table.unpack(getAllCharactersInTeam(player.Team))}
local cast = Ray.new(camera.CFrame.Position, (mouse.Hit.Position - camera.CFrame.Position).Unit*5000)
local secure = workspace:Raycast(cast.Origin, cast.Direction, params)
print(mouse.Hit.Position)
ShootEvent:FireServer(armsBarrelAttachment.WorldPosition, intoTable(secure), cast)
end
mouse.Button1Down:Connect(function()
mouseHeldDown = true
end)
mouse.Button1Up:Connect(function()
mouseHeldDown = false
end)
Tool.Activated:Connect(shoot)
Tool.Equipped:Connect(function()
contextActionService:BindAction(ReloadActionName, reload, true, Enum.KeyCode.R)
EquipSound:Play()
ToolAttach.Part1 = armTool:WaitForChild("Handle")
armTracks.holster:Play()
armTool.Parent = fpsArms
armTracks.equip:Play()
armTracks.equip:AdjustSpeed(0)
isEquipped = true
end)
Tool.Unequipped:Connect(function()
contextActionService:UnbindAction(ReloadActionName)
UnequipSound:Play()
ToolAttach.Part1 = nil
armTool.Parent = nil
armTracks.equip:Stop()
isEquipped = false
end)
ShootEvent.OnClientEvent:Connect(function(endPos: Vector3)
armTracks.shoot:Play()
armTracks.shoot:AdjustSpeed(2)
armsShootSound:Stop()
armsShootSound:Play()
flashGui.Enabled = true
task.wait(.1)
flashGui.Enabled = false
end)
ReloadEvent.OnClientEvent:Connect(function()
armTracks.reload:Play()
armTracks.reload:AdjustWeight(10)
armsReloadSound:Stop()
armsReloadSound:Play()
end)
runService.Heartbeat:Connect(function()
if runDebounce or not isEquipped or not mouseHeldDown then
return
end
runDebounce = true
shoot()
task.wait(runCd)
runDebounce = false
end)
Server Script:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local ServerModules = ServerStorage:WaitForChild("ServerModules")
local KBConstructor = require(ServerModules:WaitForChild("KBConstructor"))
local ClientRaySecure = require(ServerModules:WaitForChild("SecureClientRays"))
local ServerEvents = ServerStorage:WaitForChild("ServerEvents")
local ToolSwitchDelay = ServerEvents:WaitForChild("ToolSwitch")
local PlayerEvents = ReplicatedStorage:WaitForChild("PlayerEvents")
local DamageDisplay = PlayerEvents:WaitForChild("DamageDisplay")
local HudEvents = PlayerEvents:WaitForChild("HudEvents")
local gunAmmoClipEvent = HudEvents:WaitForChild("AmmoClipEvent")
local switchDelayEvent = PlayerEvents:WaitForChild("ToolSwitchDelay")
local effectsFolder = PlayerEvents:WaitForChild("Effects")
local tracerEvent = effectsFolder:WaitForChild("BulletTracer")
local Tool = script.Parent
local ShootEvent = Tool:WaitForChild("RemoteShoot")
local ReloadEvent = Tool:WaitForChild("RemoteReload")
local BindableReload = Tool:WaitForChild("BindableReload")
local Ammo = Tool:WaitForChild("Ammo")
local ClipSize = Tool:WaitForChild("ClipSize")
local GunFlash = Tool:WaitForChild("GunFlash")
local MuzzleFlash = GunFlash:WaitForChild("MuzzleFlash")
local Handle = Tool:WaitForChild("Handle")
local ShootSound = Handle:WaitForChild("ShootSound")
local ReloadSound = Handle:WaitForChild("ReloadSound")
local Animations = {
Idle = Tool:WaitForChild("Idle")
}
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
local shootDebounce = false
local shootcooldown = .3
local maxAmmo = 12
local maxClip = 150
local reloadCd = 2.25
local currentPlr = nil
local currentIdleTrack = nil
local currentToolAttach: Motor6D = nil
local currentCharacter: Model = nil
local minimumDist = 25
local baseDmg = 17
local function getCharacter()
return Tool.Parent
end
local function handleTracers(owner: Player, start: Vector3, clientStart: Vector3, point: Vector3, color: Color3)
for _, plr: Player in pairs(game.Players:GetPlayers()) do
if plr ~= owner then
tracerEvent:FireClient(plr, start, point, color)
else
tracerEvent:FireClient(owner, clientStart, point, color)
end
end
end
local function getRandomBulletSpread()
return Vector3.new(math.random(2975, 3100), math.random(2975, 3000), 1)/10
end
local function getAllCharactersInTeam(team: Team): {Model}
local characters = {}
for _, plr: Player in pairs(team:GetPlayers()) do
if plr.Character then
table.insert(characters, plr.Character)
end
end
return characters
end
local function reload(plr)
currentPlr = plr
if shootDebounce or ClipSize.Value <= 0 or Ammo.Value == maxAmmo then
return
end
local properties = currentCharacter:WaitForChild("Properties")
local equipmentChange: BoolValue = properties:WaitForChild("CanChangeEquipment")
equipmentChange.Value = false
shootDebounce = true
ClipSize.Value -= maxAmmo-Ammo.Value
Ammo.Value = maxAmmo
gunAmmoClipEvent:FireClient(plr, Ammo.Value, ClipSize.Value)
ReloadEvent:FireClient(plr)
ReloadSound:Stop()
ReloadSound:Play()
task.wait(reloadCd)
equipmentChange.Value = true
shootDebounce = false
end
local function shoot(plr: Player, clientPos: Vector3, result: RaycastResult, cast: Ray)
currentPlr = plr
if shootDebounce then
return
end
if Ammo.Value <= 0 then
reload(plr)
return
end
local character = getCharacter()
local head: BasePart = character:WaitForChild("Head")
local myHRP: Part = character:WaitForChild("HumanoidRootPart")
local properties = character:WaitForChild("Properties")
shootDebounce = true
Ammo.Value -= 1
MuzzleFlash.Enabled = true
ShootSound:Stop()
ShootSound:Play()
currentCharacter = character
print(result)
local secure, direction = ClientRaySecure:CheckRay(plr, result, cast, getRandomBulletSpread(), {Tool.Parent})
local hit = nil
if secure then
hit = secure.Instance
else
hit = result.Instance
end
print(hit)
if hit then
local model: Model = hit:FindFirstAncestorOfClass("Model")
if model then
local humanoid = model:FindFirstChildOfClass("Humanoid")
if humanoid then
local enemyPlr = game.Players:GetPlayerFromCharacter(model)
local isAnEnemy = false
if enemyPlr then
if enemyPlr.Team ~= plr.Team then
isAnEnemy = true
local eProp: Model = model:WaitForChild("Properties")
local playerDamagedMe: ObjectValue = eProp:WaitForChild("PlayerDamagedMe")
playerDamagedMe.Value = plr
end
end
if not enemyPlr then
isAnEnemy = true
end
if isAnEnemy then
local dmg = baseDmg
local crit = false
if hit.Name == "Head" then
dmg *= 3
crit = true
end
if (direction.Magnitude) > minimumDist then
dmg -= 5
end
dmg = math.round(dmg)
humanoid:TakeDamage(dmg)
KBConstructor.new(model:WaitForChild("HumanoidRootPart"), myHRP.CFrame.LookVector.Unit, 25)
DamageDisplay:FireClient(plr, secure ~= nil and secure.Position or result.Position, crit and true or false, dmg)
end
end
end
end
handleTracers(plr, GunFlash.Position, clientPos, secure ~= nil and secure.Position or result.Position or GunFlash.Position+direction, plr.TeamColor.Color)
ShootEvent:FireClient(plr)
gunAmmoClipEvent:FireClient(plr, Ammo.Value, ClipSize.Value)
task.wait(3/60)
MuzzleFlash.Enabled = false
task.wait(shootcooldown)
shootDebounce = false
end
Tool.Equipped:Connect(function()
local character = getCharacter()
local humanoid = character:FindFirstChildOfClass("Humanoid")
local rightHand = character:WaitForChild("RightHand")
currentToolAttach = rightHand:WaitForChild("ToolAttach")
currentToolAttach.Part1 = Handle
currentPlr = game.Players:GetPlayerFromCharacter(Tool.Parent)
params.FilterDescendantsInstances = {character, table.unpack(currentPlr.Team:GetPlayers())}
currentIdleTrack = humanoid:LoadAnimation(Animations.Idle)
currentIdleTrack:AdjustSpeed(0)
currentIdleTrack:Play()
gunAmmoClipEvent:FireClient(currentPlr, Ammo.Value, ClipSize.Value)
shootDebounce = true
task.wait(.15)
shootDebounce = false
end)
Tool.Unequipped:Connect(function()
currentToolAttach.Part1 = nil
gunAmmoClipEvent:FireClient(currentPlr, "", "")
currentIdleTrack:Stop()
ToolSwitchDelay:Fire(currentPlr, Tool)
end)
BindableReload.Event:Connect(reload)
ReloadEvent.OnServerEvent:Connect(reload)
ShootEvent.OnServerEvent:Connect(shoot)
I’m pretty sure the module script isn’t edit but here it is anyway:
local Security = {}
Security.MaxOriginDistance = 5
--direction = target - origin
function Security:CheckRay(owner: Player, result: RaycastResult, cast: Ray, bulletSpread: Vector3, filter: {Instance})
local origin = cast.Origin
local direction = (cast.Direction.Unit)*bulletSpread
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Include
params.FilterDescendantsInstances = {workspace.Map}
params:AddToFilter(filter)
local primaryPart = owner.Character.PrimaryPart
if (primaryPart.Position - origin).Magnitude >= Security.MaxOriginDistance then
origin = primaryPart.Position
end
local newResult = workspace:Raycast(origin, direction, params)
return newResult, direction
--[[
if newresult then something is obstructing the ray
if not newresult, then the clientRay is secure
]]--
end
return Security