During nighttime, a knife model from Lighting will be cloned to the player’s backpack.
Once night is over, the player’s inventory will clear. (I would prefer it to be the knife is removed but I don’t know how to do that. So if anybody does, that would be cool.)
My script:
local Lighting = game:GetService("Lighting") -- get lighting
game.Players.PlayerAdded:connect(function(player)
Lighting:GetPropertyChangedSignal("ClockTime"):Connect(function()
if Lighting.ClockTime <= 5 or Lighting.ClockTime >= 20 then -- if night
local knife = game.Lighting.Knife:Clone()
knife.Parent = player.Backpack -- clone and move to player backpack
print("Knife was given")
end
if Lighting.ClockTime >= 5 or Lighting.ClolckTime <= 20 then
player.Backpack:ClearAllChildren()
print("Backpack cleared")
end
end
end)
end)
My problem:
The code works, but it spams knifes and will not stop. I tried fixing this by adding wait(540) … that is how long nighttime is… at the end of the code but it did not work.
local Lighting = game:GetService("Lighting") -- get lighting
game.Players.PlayerAdded:connect(function(player)
Lighting:GetPropertyChangedSignal("ClockTime"):Connect(function()
if Lighting.ClockTime <= 5 or Lighting.ClockTime >= 20 then -- if night
if not player.Backpack:FindFirstChild("Knife") then
local knife = game.Lighting.Knife:Clone()
knife.Parent = player.Backpack -- clone and move to player backpack
print("Knife was given")
else
warn("Player already has knife.")
end
end
if Lighting.ClockTime >= 5 or Lighting.ClockTime <= 20 then
player.Backpack:ClearAllChildren()
print("Backpack cleared")
end
end)
end)
You’ll also want to account for the case where a player has the knife equipped right before the nighttime period ends, if I’m not mistaken. A tool doesn’t only exist within the backpack in an active game. When it’s equipped, it’ll be moved to the character.
Thank you so much for the response! Although, I tested out the script, and the knife does not appear; it just spams the print in the output bar. Any ideas?
if Lighting.ClockTime <= 5 or Lighting.ClockTime >= 20 then -- if night
if not player.Backpack:FindFirstChild("Knife") then
if not player.Character:FindFirstChild("Knife") then
local knife = game.Lighting.Knife:Clone()
knife.Parent = player.Backpack -- clone and move to player backpack
print("Knife was given")
end
else
warn("Player already has knife.")
end
end
I think that part’s fine. It’s right here that I’m referring to:
if Lighting.ClockTime >= 5 or Lighting.ClockTime <= 20 then
player.Backpack:ClearAllChildren()
print("Backpack cleared")
end
This code is removing the knife from the backpack once the night is over, right?
But what if, just right before the night is over, the player still has the knife equipped so that its in the character?
That means player.Backpack:ClearAllChildren() won’t do much because it’d be clearing no tools.
To fix it, you’d want to see if the knife exists inside the character and destroy it there, then check the backpack if it doesn’t exist in the character.
Also, ClearAllChildren works great but what if the OP decides to add more tools in the future? You might want to edit it so that the solution is future-proof for more tools. (Destroy the knife specifically, nothing else).
There’s also another major problem with the current code! A potential memory leak. Basically just remove the nested connections (remove PlayerAdded from all of it)
if player.Backpack:FindFirstChild("Knife") then
player.Backpack:FindFirstChild("Knife"):Destroy()
elseif player.Character:FindFirstChild("Knife") then
player.Character:FindFirstChild("Knife"):Destroy()
end
if Lighting.ClockTime <= 5 or Lighting.ClockTime <= 20 then
if player.Backpack:FindFirstChild("Knife") then
player.Backpack:FindFirstChild("Knife"):Destroy()
print("Knife cleared")
elseif player.Character:FindFirstChild("Knife") then
player.Character:FindFirstChild("Knife"):Destroy()
print("Knife cleared")
end
end
-- LocalScript
local replicatedStorage = game:GetService("ReplicatedStorage")
local giveKnifeEvent = replicatedStorage.GiveKnifeEvent
local removeKnifeEvent = replicatedStorage.RemoveKnifeEvent
local lighting = game:GetService("Lighting")
lighting:GetPropertyChangedSignal("ClockTime"):Connect(function()
local currentClockTime = lighting.ClockTIme
if (currentClockTime <= 5 or currentClockTime >= 20) then
giveKnifeEvent:FireServer()
elseif (currentClockTime >= 5 or currentClockTIme <= 20) then
removeKnifeEvent:FireServer()
end
end)
^^^I haven’t worked with ClockTime as much so I only used the same checks as you did.
-- Script
local replicatedStorage = game:GetService("ReplicatedStorage")
local giveKnifeEvent = replicatedStorage.GiveKnifeEvent
local removeKnifeEvent = replicatedStorage.RemoveKnifeEvent
local knifeToolName = "Knife"
local knife = -- Refer to your knife here
giveKnifeEvent.OnServerEvent:Connect(function(player)
local character = player.Character
if (character) then
local backpack = player.Backpack
local isKnifeInChar = character:FindFirstChild(knifeToolName)
local isKnifeInBackpack = backpack:FindFirstChild(knifeToolName)
if (isKnifeInChar or isKnifeInBackpack) then
return
end
local knifeClone = knife:Clone()
knifeClone.Parent = backpack
end
end)
removeKnifeEvent.OnServerEvent:Connect(function(player)
local character = player.Character
if (character) then
local backpack = player.Backpack
local knifeInChar = character:FindFirstChild(knifeToolName)
local knifeInBackpack = backpack:FindFirstChild(knifeToolName)
if (knifeInChar) then
knifeInChar:Destroy()
elseif (knifeInBackpack) then
knifeInBackpack:Destroy()
end
end
end)
It’s a lot more than the original but this is the way it had to be done to respect FilteringEnabled, if I’m not wrong.
@triisflame You’ll need to create two remote events and refactor your code based on this.
If I’m not crazy, this should work fine if you port it properly. (Don’t copy and paste, try to rewrite it in your codebase).
Unless the time is changing on the client only (unlikely the case) why not just loop through all the players if the new time is <= 5, >= 20, >= 5 or <= 20?
That is another way you can go about it ! Personally I’d still stick with using remotes and their events because it’ll help keep the client side cleaner and more separated from the server side.
Imagine if the OP wants something to happen locally to the player after the knife is given.
With your suggestion, you’d have to rely on extra functionality like FireClient/FireAllClients on the server side instead of just being able to write to the LocalScript directly.
But it really doesn’t matter, feel free to write an alternative solution using a loop on the server side.
I understand that but you also shouldn’t use unnecessary remotes. It seems like the only functionality of this script is to give or remove player’s knives whenever it is a certain time of day.
Two remotes sending no arguments except the player who fired wouldn’t really have a major effect! I wouldn’t worry about choosing my solution against your suggestion because a lot of Roblox games use many remotes anyway while still maintaining their performance. It’s not unnecessary because this is what the client-server model requires for Roblox games to function!
I think it’s a matter of quality over quantity.
It doesn’t make sense using PlayerAdded and Light change in one script smh.
I am guessing this is what you are looking for?
local Lighting = game:GetService("Lighting")
local There = false
local function GiveKnife(Player: Player)
local knife = Lighting.Knife:Clone()
local Backpack = Player:FindFirstChild("Backpack")
knife.Parent = Backpack
print("Knife was given")
end
local function RemoveKnife(Player: Player)
local Character = Player.Character or Player
local Backpack = Player:FindFirstChild("Backpack") or Player
local Knife = Character:FindFirstChild("Knife") or Backpack:FindFirstChild("Knife")
if Knife then
Knife:Destroy()
end
print("Knife was Removed ")
end
Lighting:GetPropertyChangedSignal("ClockTime"):Connect(function()
if Lighting.ClockTime <= 5 or Lighting.ClockTime >= 20 and not There then -- if night
for i, v in pairs(game:GetService("Players"):GetPlayers()) do
GiveKnife(v)
end
There = true
end
if Lighting.ClockTime >= 5 or Lighting.ClolckTime <= 20 and There then
for i, v in pairs(game:GetService("Players"):GetPlayers()) do
RemoveKnife(v)
end
There = false
end
end
end)
end)
Something like this should be what you’re looking for, although @magical_artistery’s solution would work just as well. Depends on which approach you would rather take.
local players = game:GetService("Players")
local lighting = game:GetService("Lighting")
local knife = lighting.Knife
local function giveKnives()
for _, player in players:GetPlayers() do
if not player.Backpack:FindFirstChild("Knife") and not player.Character:FindFirstChild("Knife") then
local newKnife = knife:Clone()
newKnife.Parent = player.Backpack
end
end
end
local function removeKnives()
for _, player in players:GetPlayers() do
local knifeCheck = player.Backpack:FindFirstChild("Knife") or player.Character:FindFirstChild("Knife")
if knifeCheck then
knifeCheck:Destroy()
end
end
end
lighting:GetPropertyChangedSignal("ClockTime"):Connect(function()
local clockTime = lighting.ClockTime
if clockTime <= 5 or clockTime >= 20 then
giveKnives()
elseif clockTime >= 5 or clockTime <= 20 then
removeKnives()
end
end)