We use cookies on this site to enhance your user experience

Sep 14 2018, 5:13 PM PST

-- This script handles blaster events on the client-side of the game

-- How fast the projectile moves
local PROJECTILE_SPEED = 40
-- How often a projectile can be made on mouse clicks (in seconds)
local LAUNCH_COOLDOWN = 1
-- How far away the projectile is created from the front of the player
local PROJECTILE_OFFSET = 4

-- Variables for Roblox services
local ContextActionService = game:GetService("ContextActionService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- Variables for RemoteEvents and Functions (see the BlasterHandler Script)
local launchProjectile = ReplicatedStorage:WaitForChild("LaunchProjectile")
local destroyProjectile = ReplicatedStorage:WaitForChild("DestroyProjectile")
local destroyEnemy = ReplicatedStorage:WaitForChild("DestroyEnemy")
local ping = ReplicatedStorage:WaitForChild("Ping")

-- Variable to store the basic projectile object
local projectileTemplate = ReplicatedStorage:WaitForChild("BlasterProjectile")
-- Variable for the player object
local player = Players.LocalPlayer

local canLaunch = true

-- Fires when the player clicks the mouse
local function onLaunch()
	-- Only launch if the player's character exists and the blaster isn't on cooldown
	if player.Character and canLaunch then
		-- Prevents the player from launching again until the cooldown is done
		canLaunch = false
		spawn(function()
			wait(LAUNCH_COOLDOWN)
			canLaunch = true
		end)
		
		-- Create a new projectile
		local projectile = projectileTemplate:Clone()
		local playerCFrame = player.Character.PrimaryPart.CFrame
		local direction = playerCFrame.LookVector
		projectile.Position = playerCFrame.Position + direction * PROJECTILE_OFFSET
		projectile.Velocity = direction * PROJECTILE_SPEED
		
		-- Zero out gravity on the projectile so it doesn't fall through the ground
		local mass = projectile:GetMass()
		projectile.VectorForce.Force = Vector3.new(0, 1, 0) * mass * game.Workspace.Gravity
		
		-- Put the projectile in the workspace
		projectile.Parent = game.Workspace
		
		-- Tell the server to create a new projectile and send it back to us
		local serverProjectile = launchProjectile:InvokeServer(projectile.Position, projectile.Velocity)
		-- Hide the server copy of the projectile
		serverProjectile.LocalTransparencyModifier = 1
		
		-- Set up touched event for the projectile
		projectile.Touched:Connect(function(other)
			-- The only collisions we care about are those with enemies and with walls
			if other.Name == "EnemyBall" or other.Name == "Wall" then
				-- Hit an enemy or wall, destroy the projectile and tell the server to destroy its copy
				projectile:Destroy()
				destroyProjectile:FireServer(serverProjectile)
				
				-- Hit an enemy, destroy it and tell the server to destroy it as well
				if other.Name == "EnemyBall" then
					destroyEnemy:FireServer(other)
					other:Destroy()
				end
			end
		end)
	end
end

-- Connect a function to the ping RemoteFunction. This can be empty because all
-- the server needs to hear is a response
ping.OnClientInvoke = function() end

ContextActionService:BindAction("Launch", onLaunch, false, Enum.UserInputType.MouseButton1)