Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Local variables
- local tool = script.Parent
- local currentAmmo = tool.Configurations.ClipSize.Value
- local canFire = true
- local reloading = false
- local fireSound = tool.FireSound
- -- Configurable variables
- local attackCooldown = tool.Configurations.AttackCooldown.Value
- local range = tool.Configurations.Range.Value
- local damage = tool.Configurations.Damage.Value
- local reloadTime = tool.Configurations.ReloadTime.Value
- local clipSize = tool.Configurations.ClipSize.Value
- -- Setup Remote Events
- local function createEvent(eventName)
- local event = game.ReplicatedStorage:FindFirstChild(eventName)
- if not event then
- event = Instance.new("RemoteEvent", game.ReplicatedStorage)
- event.Name = eventName
- end
- return event
- end
- local updateEvent = createEvent("ROBLOX_PistolUpdateEvent")
- local equipEvent = createEvent("ROBLOX_PistolEquipEvent")
- local unequipEvent = createEvent("ROBLOX_PistolUnequipEvent")
- local fireEvent = createEvent("ROBLOX_PistolFireEvent")
- local reloadEvent = createEvent("ROBLOX_PistolReloadEvent")
- -- Add tracer decal to server storage if it isn't already there
- if not game.ServerStorage:FindFirstChild("ROBLOX_PistolTracerDecal") then
- tool.ROBLOX_PistolTracerDecal:Clone().Parent = game.ServerStorage
- end
- -- Bind function to update event. Used to update player's orientation if FilteringEnabled
- -- is true (otherwise the rotation would not replicate from the rotating player)
- updateEvent.OnServerEvent:connect(function(player, neckC0, rshoulderC0)
- local character = player.Character
- character.Torso.Neck.C0 = neckC0
- character.Torso:FindFirstChild("Right Shoulder").C0 = rshoulderC0
- end)
- -- Bind functions to when player equips/unequips the tool. Right now just need to turn on and
- -- off AutoRotate
- equipEvent.OnServerEvent:connect(function(player)
- player.Character.Humanoid.AutoRotate = false
- end)
- unequipEvent.OnServerEvent:connect(function(player)
- player.Character.Humanoid.AutoRotate = true
- end)
- -- Creates "bullet". No projectile motion is actually used. Pistol raytraces to target and creates
- -- a tracer trail to the target. Fading trail gives illusion of motion.
- local function createBullet(target)
- -- Get actual handle position. Want to offset from the center of the handle as the bullet comes
- -- from the barrel of the gun
- local handlePos = tool.Handle.CFrame + tool.Handle.CFrame:vectorToWorldSpace(Vector3.new(0,0,.3))
- local toTarget = handlePos:vectorToWorldSpace(Vector3.new(0,1,0)) * 200
- local torsoLook = (tool.Parent:FindFirstChild("Torso").CFrame.lookVector * Vector3.new(1,0,1)).unit
- local toTargetAngle = (toTarget * Vector3.new(1,0,1)).unit
- local angle = math.acos(torsoLook:Dot(toTargetAngle))
- -- Checks angle from where the character is facing to the orientation of the pistol. If the angle
- -- is less than 90 degress then we shoot to where the mouse is pointing (helps accuracy). Otherwise
- -- the gun is assumed at the edge of its rotation and just shoots straight.
- if math.deg(angle) < 90 then
- toTarget = target - tool.Handle.Position
- if toTarget.magnitude > range then
- toTarget = toTarget.unit * range
- end
- toTarget = toTarget * 1.1
- end
- -- Shoot ray and check if humanoid was hit. If so, it should take damage
- local ray = Ray.new(handlePos.p, toTarget)
- local part, position = game.Workspace:FindPartOnRay(ray, tool.Parent)
- if part and part.Parent and part.Parent:FindFirstChild("Humanoid") then
- part.Parent:FindFirstChild("Humanoid"):TakeDamage(damage)
- end
- if position then
- toTarget = position - handlePos.p
- end
- -- Create tracer trail. Trail is made of thin parts 2 studs long. Fades each segment
- -- starting with closest tracer to the tool.
- local bulletTrail = Instance.new("Model", game.Workspace)
- local trailTable = {}
- -- Fetch decal from server storage
- local decal = game.ServerStorage.ROBLOX_PistolTracerDecal
- for i = 0, toTarget.magnitude/2, 1 do
- local trailSegment = Instance.new("Part", bulletTrail)
- trailSegment.CanCollide = false
- trailSegment.Anchored = true
- trailSegment.FormFactor = Enum.FormFactor.Custom
- trailSegment.Size = Vector3.new(.1,.1,2)
- trailSegment.BrickColor = BrickColor.White()
- trailSegment.CFrame = CFrame.new(handlePos.p + (toTarget.unit * 2 * (i + .5)), handlePos.p)
- trailSegment.Transparency = 1
- -- Add point light to tracer for a little illumination
- local light = Instance.new("PointLight", trailSegment)
- light.Range = 3
- -- Add decal to faces of the part
- local function addDecal(face)
- local decalClone = decal:Clone()
- decalClone.Parent = trailSegment
- decalClone.Face = face
- end
- addDecal(Enum.NormalId.Top)
- addDecal(Enum.NormalId.Bottom)
- addDecal(Enum.NormalId.Left)
- addDecal(Enum.NormalId.Right)
- -- Add segment to all of the tracers
- table.insert(trailTable, trailSegment)
- end
- -- Coroutine thread to fade each trail segment. Put in coroutine so it does not
- -- block the rest of the pistol's script
- local fadeThread = coroutine.create(function()
- local count = 1
- local ended = false
- -- Keep looping until end condition is met
- while not ended do
- -- Assume end condition is met. Easier to switch it off later if we need to
- -- keep looping
- ended = true
- -- Loop through every part in the trail
- for index, part in pairs(trailTable) do
- if index <= count then
- local shouldDestroy = false
- for _, face in pairs(part:GetChildren()) do
- if face:IsA("Decal") then
- -- Increase decal transparencies and use this to determine if
- -- segment has completely faded
- face.Transparency = face.Transparency + .05
- if face.Transparency < 1 then
- ended = false
- else
- shouldDestroy = true
- end
- else
- -- Dim the point light
- face.Brightness = face.Brightness - .1
- end
- end
- -- If segment is completely faded then clean it up
- if shouldDestroy then
- table.remove(trailTable, index)
- part:Destroy()
- end
- end
- end
- count = count + 1
- wait()
- end
- bulletTrail:Destroy()
- end)
- coroutine.resume(fadeThread)
- end
- -- Function to bind to reload event
- local function reload()
- if not reloading then
- tool.ReloadSound:Play()
- reloading = true
- canFire = false
- wait(reloadTime)
- currentAmmo = clipSize
- canFire = true
- reloading = false
- end
- end
- reloadEvent.OnServerEvent:connect(reload)
- -- Bind function to fire event
- fireEvent.OnServerEvent:connect(function(player, target)
- if tool.Parent == player.Character then
- -- If tool has enough shots then fires. Otherwise reloads.
- if currentAmmo <= 0 then
- return reload()
- end
- if canFire then
- canFire = false
- currentAmmo = currentAmmo - 1
- fireSound:Play()
- createBullet(target)
- delay(attackCooldown, function()
- canFire = true
- end)
- end
- end
- end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement