I’ve decided to remake discontinued game to learn to code.
I’ve made a scanning tool. If you press and hold left mouse, a beam is created from the nozzle to the object. If the object is an NPC, a gui appears displaying its HP, name and aggression (Hostile, etc).
If it’s an ore deposit, after scanning it for long enough you obtain ore. A block in the deposit is then destroyed.
I wish this code to be more efficient. It would be great if it could work on mobile too somehow.
A known improvement is not firing an event which is detected by the same script, although I feel it may require a coroutine and my attempts thus far at learning to use it elsewhere have failed miserably.
I have a localscript in the tool which detects if its Activated and sends the mouse position and player through an event to a server script inside the tool which handles the rest.
A known bug is, for some reason, after collecting one ore a 2nd ore quickly gets extracted with it.
Concider that multiple players may choose to extract from the same deposit, and that deposits have limited ore.
Local:
local mouse = game.Players.LocalPlayer:GetMouse()
local joe = false
script.Parent.Activated:Connect(function()
joe = true
while joe == true do
script.Parent.Fire:FireServer(mouse.Hit.Position)
wait(.01)
end
end)
script.Parent.Deactivated:Connect(function()
joe = false
script.Parent.Fire:FireServer()
end)
Server:
local SS = game:GetService("ServerStorage")
local SSS = game:GetService("ServerScriptService")
local RS = game:GetService("ReplicatedStorage")
local tool = script.Parent
local shoot_part = tool:WaitForChild("Shoot")
local playerData = require(SSS.PlayerData)
local guiEvent = RS.RemoteEvents.ScanGui
local lastScan = nil
local currentScan = nil
local scanning = false
script.Parent.Fire.OnServerEvent:Connect(function(player,mousePos) --Makes raycast
print("hi")
if mousePos then
local rayParam = RaycastParams.new() --Blacklists player model/decendants
rayParam.FilterDescendantsInstances = {player.Character}
rayParam.FilterType = Enum.RaycastFilterType.Blacklist
local origin = shoot_part.Position --Setting up and firing raycast
local direction = (mousePos - origin).Unit
local result = workspace:Raycast(shoot_part.Position, direction*30,rayParam)
if result then
if result.Instance.Parent ~= lastScan then --Checks if no longer scanning the same thing
lastScan = result.Instance.Parent
scanning = false
end
if result.Instance.Parent:FindFirstChild("Scannable") and scanning == false then
script.Parent.Scan:Fire(player,result,lastScan)
--Fires event to scan if not already scanning, and if thing is scannable
end
local pre = workspace.Terrain:FindFirstChild(player.Name)
--checks if attatchment exists for the beam to end at
if pre then
pre.Position = result.Position --moves attatchment to scanning location
else
local attachment = Instance.new("Attachment") --makes new attacthment if no attatchment
attachment.Parent=workspace.Terrain
attachment.Name=player.Name
attachment.Position = result.Position
script.Parent.Beam1.Attachment1 = attachment
script.Parent.Beam2.Attachment1 = attachment
end
else --if raycast didnt find anything, destroys attatchment(ends scan beam)
local jane = workspace.Terrain:FindFirstChild(player.Name)
if jane then
jane:Destroy()
end
end
else
scanning = false
local jane = workspace.Terrain:FindFirstChild(player.Name)
if jane then
jane:Destroy()
end
end
end)
script.Parent.Scan.Event:Connect(function(player,result,lScan) --Begins the extraction process
scanning = true
--Checking for the strValue/type of object scanned
local Type = result.Instance.Parent.Scannable:FindFirstChild("Type")
if Type and Type.Value == "NPC" and result.Instance.Parent.Humanoid.Health > 0 then
player.PlayerGui.ScanGui.NPCGui.BG.HPBG.Humanoid.Value = result.Instance.Parent.Humanoid
guiEvent:FireClient(player,result.Instance.Parent.Name) --Displays details of the npc as a Gui
else --if its ore thats scanned, give ore if scanning for long enough
local ore = result.Instance.Parent
local element = ore.Scannable.Value --what ore is it? strValue
local x = 0
while result.Instance.Parent == lScan and scanning == true do
x+= 1
if x == 3 then
scanning = false
if ore.Remain.Value > 0 then
ore:FindFirstChild(element..ore.Remain.Value):Destroy()
ore.Remain.Value -=1
SS.giveXp:Fire(ore.Exp.Value, player)
playerData.upData(player,"items",element,1,0) --modulescript which handles data
end
else
wait(1)
end
end
end
end)