For this I would simplify the code, you don’t need to create a table and add all of the children to the table because :GetChildren() already returns a table with all of it’s children.
Also I noticed that you were setting the CFrame and Parent of the original tool instead of the cloned tool.
Here is some simplified code that should work in terms of creating a new battery at a random spawn:
local folder = workspace.Spawn
local tool = game.Workspace.Battery
local toolSpawns = folder:GetChildren()
local clone = tool:Clone()
clone.CFrame = toolSpawns[math.random(1,#toolSpawns)].CFrame + Vector3.new(0,1,0) --//Picks one random spawn's CFrame with Y offset of 1 stud.
clone.Parent = workspace
Do you just want one battery spawned at all times that changes positions whenever a player picks it up? I’m just trying to understand what you’re going for.
Okay, so for instance if the Player picks up the Battery it will re-position the current Battery (the Battery the Player has picked up) and will place the Battery to one of the positions listed as “Spawn”.
(I was referring to the topic stuff rather than the current stuff)
When equipping the flashlight, have an ObjectValue called CurrentFlashlight, within the flashlight have the amount of battery remaining, if a full battery lasts only 2 minutes, put 120 seconds has the max battery it can hold.
Use RunService to transition smoothly between a full, to empty battery, like so:
-- when RunService is active
local Tool = CurrentFlashlight.Value -- Tool
local CurrentBattery = Tool:GetAttribute("CurrentBattery")
-- the current amount that is within the battery
local FullBattery = Tool:GetAttribute("FullBattery")
-- the amount of time for a full battery
Tool:SetAttribute("CurrentBattery", math.clamp(CurrentBattery - dt, 0, FullBattery)
-- math.clamp will help set a limit to where the battery will go, it cant pass 0
-- but it also cant pass the FullBattery capacity.
-- DeltaTime is the time between each frame, you can use it to subtract from
-- your Current Battery until you reach 0
local Percentage = math.floor(Tool:GetAttribute("CurrentBattery")/FullBattery)*100
-- percentage of the Battery
-- might be useful for UI purposes
Because this a Client related visual effect, keep this on the Client, but if you want to prevent exploitation, have the Server confirm current values.
You could add these two functions for giving the player the battery and then moving it to a random spawn:
local folder = workspace.Spawn
local Tool = game.Workspace.Battery
local function pickupBattery()
local batteryClone = Tool:Clone()
batteryClone.Parent = player.Backpack
end
local function moveBattery()
local toolSpawns = folder:GetChildren()
Tool.CFrame = toolSpawns[math.random(1,#toolSpawns)].CFrame + Vector3.new(0,1,0) --//Picks one random spawn's CFrame with Y offset of 1 stud.
end
ProximityPrompt.Triggered:connect(function(Player)
if Player and Player.Character then
local Backpack = Player:WaitForChild("Backpack")
for i = 1, #ToolNames do
local Tool = Storage:FindFirstChild(ToolNames[i])
if Tool then
if Backpack:FindFirstChild(Tool.Name) == nil then
moveBattery()
pickupBattery()
end
end
end
end
end)
I generally wouldn’t recommend storing tools in the workspace but if you do make sure you unanchor the tool so that the player can properly equip it.
local ToolNames = {"Battery"} -- Change Item to your item name and move it to ServerStorage
local Storage = game.ServerStorage.RareItems
local Part = script.Parent
local ProximityPrompt = Part:WaitForChild("ProximityPrompt")
local folder = workspace.Map.Zones.BatteryZone
local tool = game.Workspace.Map.KillArea.Batteries.Battery
local function pickupBattery()
local batteryClone = Tool:Clone()
batteryClone.Parent = Tool.Backpack
end
local function moveBattery()
local toolSpawns = folder:GetChildren()
Tool.CFrame = toolSpawns[math.random(1,#toolSpawns)].CFrame + Vector3.new(0,1,0) --//Picks one random spawn's CFrame with Y offset of 1 stud.
end
ProximityPrompt.Triggered:connect(function(Player)
if Player and Player.Character then
local Backpack = Player:WaitForChild("Backpack")
for i = 1, #ToolNames do
local Tool = Storage:FindFirstChild(ToolNames[i])
if Tool then
if Backpack:FindFirstChild(Tool.Name) == nil then
moveBattery()
pickupBattery()
end
end
end
end
end)
-- I didnt coded all the scriot, I just changed it from click to pick up to E to pick up
It is giving me this error – 04:30:36.289 Workspace.Map.KillArea.Batteries.Battery.PickUpScript:13: attempt to index nil with 'Backpack' - Server - PickUpScript:13
Wait is this in a local script or server script? You don’t have a player variable for that function. Either way, if you pass the Player parameter from the ProximityPrompt’s Triggered event to the pickupBattery function that will work.
Here is what the new code would look like:
local ToolNames = {"Battery"} -- Change Item to your item name and move it to ServerStorage
local Storage = game.ServerStorage.RareItems
local Part = script.Parent
local ProximityPrompt = Part:WaitForChild("ProximityPrompt")
local folder = workspace.Map.Zones.BatteryZone
local tool = game.Workspace.Map.KillArea.Batteries.Battery
local function pickupBattery(Player)
local batteryClone = Tool:Clone()
batteryClone.Parent = Player.Backpack
end
local function moveBattery()
local toolSpawns = folder:GetChildren()
Tool.CFrame = toolSpawns[math.random(1,#toolSpawns)].CFrame + Vector3.new(0,1,0) --//Picks one random spawn's CFrame with Y offset of 1 stud.
end
ProximityPrompt.Triggered:connect(function(Player)
if Player and Player.Character then
local Backpack = Player:WaitForChild("Backpack")
for i = 1, #ToolNames do
local Tool = Storage:FindFirstChild(ToolNames[i])
if Tool then
if Backpack:FindFirstChild(Tool.Name) == nil then
moveBattery()
pickupBattery(Player)
end
end
end
end
end)
How about we make it that when the Player gets the Battery it will Destroy() the current Battery (the Battery the Players has just achieved) and wait (1) then the Battery will Spawn in a different area.