Alright, the title might sound bizarre, but after I explain it will make sense. Basically I have a consumable item that get’s destroyed after eating it, but the effects are meant to wear off after some time. The issue with that though is the server script in the tool intended to add AND remove the effects of the item would get destroyed after adding the effects, so anything like task.delay, task.wait or a coroutine wouldn’t work as they would be cancelled due to well, obviously the script doesn’t exist anymore. (Because the parent / the tool got destroyed incase it wasn’t clear)
In the past I have dealt with stuff like this in a unique way. Basically what I would do is write another simple server script that would do said effects that the destroyed script couldn’t quite do. Then, I would make it so that that script Immediately runs when enabled, and you will know why in a second. Then, I put that server script into the tool’s server storage assets (where I keep all other additional stuff the tool might need like models, but not including animations or audio). Then, I disable the script in server storage. Then, what I do is make the script inside the tool / consumable, before destroying itself and the tool, will copy that script from the server storage, say into the player or wherever makes sense, and then enables the script.
So said simply, before destroying itself, it makes another script tick down and finally remove the players effects before destroying itself as well, all while the original script and even tool don’t exist anymore. But I was wondering, surely there must be a better way to do this, so that’s where this post comes in, is there a better way of doing this? (Also do I need to disable scripts if they are in serverstorage?)
How you organize this, and what instance you tie the lifetime of the effect too depends a bit on what you mean by “effect”. If it’s something like an audio-visual effect, like sounds or particles on the player’s character, then DebrisService can be used to schedule the cleanup. This would be OK for something that’s just a cosmetic effect, which does not need to persist through a character respawn, or server rejoin.
If, on the other hand, what you mean by “effect” is something thing that effects game state and gameplay, like a damage buff or shield status effect, or something, then you probably want to have your own server-side manager singleton that handles adding and removing effects from players. This way, you’d have server-side control of when they expire and get cleaned up, and could have them persist through respawns or rejoins so that someone could not respawn to cheat their way out of a debuff, for example. In this kind of system, your consumable tool would do nothing more than send an event to this effect manager script, which would handle scheduling the expiration and removal.
I was talking about the latter. So like, a module script in the server script service? And you then use that module scripts functions to apply said buffs?
I strongly suggest you take take the advise of the above reply, and use module scripts to create a modular system for your tools.
With that being said, to answer the question posed in the title: You can make a script continue to run after being destroyed, by wrapping your code in a do end.
I would not recommend you do this, as a matter of fact I would not recommend you ever delete scripts, however you can do this.
do
script:Destroy() -- Script is destroyed
task.wait(5)
print("Still runs") -- 5 seconds later, this print still runs
end
here’s part of a grenade script for my game, that needs to remove the tool from the player’s backpack while still running a function for the new thrown grenade.
-- When the player activates the tool
script.Parent.Activated:Connect(function()
local player = Players:GetPlayerFromCharacter(script.Parent.Parent)
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:FindFirstChildOfClass("Humanoid")
-- Load and play animations
local pullTrack = humanoid:LoadAnimation(pullAnimation)
local throwTrack = humanoid:LoadAnimation(throwAnimation)
pullTrack:Play()
pinSound:Play()
pullTrack.Stopped:Wait()
throwTrack:Play()
-- Clone the grenade handle part to simulate a thrown grenade
local grenade = handle:Clone()
grenade.Name = "Thrown Grenade"
grenade.Explode.PlayOnRemove = true
-- Remove the tool from the player's inventory
script.Parent.Parent = nil
-- Throw the grenade after a brief delay for the animation
task.delay(0.15, function()
if grenade then
throwGrenade(player, grenade)
end
end)
end)
sorry for late reply, I have thought about making a item class / modular system and I am thinking on making it one, I already somewhat know how module scripts and modular systems work but thanks for the idea
You don’t actually need to have the script be inside the tool for it to function. The scripts can be placed anywhere else, as long as you have a way to reference the tool object. This would prevent the need to destroy the script at all.
I’m aware of that just, uh well thats kinda how I make all my tools in my game currently. (Main reason being I don’t want 100 item scripts in server script service or something like that.)
yeah, you could actually just put a tag on anything thats a consumable, then add attributes for its healing or whatever consumables do. then there can just be one script that detects when the tool is destroyed or something similar.
This is a cool method and I might actually do this, so does the logic basically continue even though the parent isn’t the player anymore? Also other thing, does the references to things still work, I can’t quite remember how object references go when moving the tool or something part of the reference
you could probably just save the attributes as variables and access them after the tool is destroyed. logic will continue as long as the script is in workspace or ServerScriptService, i believe.
Make your effect something you call as a remote… Do the effect from the other script. Pretty much the best practice anyways to keep things secure. Client is just the trigger and maybe some information passed to be used by the server script. If that is possible here. If this needs to be a client script you can still remote to a different one.
Then, you could just write something like this in the script for the tool.
local tool = script.Parent
local char
tool.Equipped:Connect(function()
char = tool.Parent
end)
tool.Activated:Connect(function()
game.ServerScriptService.Event:Fire(char, 1)
tool:Destroy()
end)
I know it’s a bit overkill for like ONE tool but it’s useful if you want the effect to be reused elsewhere. It’s the most reliable way I could think of for doing this.