Hye there everyone, been having issues with my bomb script. I have a function that resizes the part acting as an explosion and changes the properties of the parts it collides with. But whenever the part resizes, it runs the function over and over again, applying the changes multiple times. I want to prevent the properties being duplicated within the parts affected.
I have browsed the DevForum but couldn’t find any solutions.
Any and all help is appreciated!
P.S. script may look appalling as I am relatively new to scripting.
wait(5)
local PlasmaEmitter = script.Parent.PlasmaEmitter
PlasmaEmitter.Enabled = true
local debounce = false
-- Plasma Ball Functions
script.Parent.Anchored = true
script.Parent.CanCollide = false
function onTouched(hit)
if hit:IsA("Part") and hit.Name ~= "HumanoidRootPart" and hit.CollisionGroup ~= "Bombs&Coins" or hit:IsA("WedgePart") then
hit.BrickColor = script.Parent.BrickColor
hit.Material = "Granite"
hit.Reflectance = 0.2
hit.Transparency = 0.2
script.Parent.PlasmaHurtPlayer:Clone().Parent = hit
script.Parent.PlasmaHurtPlayer.Disabled = false
else
if hit.Parent:FindFirstChild("Humanoid") then
if debounce == false then
debounce = true
local dmg = 15
hit.Parent.Humanoid:TakeDamage(dmg)
wait(.5)
hit.Parent.Humanoid:TakeDamage(dmg)
wait(.5)
hit.Parent.Humanoid:TakeDamage(dmg)
wait(.5)
debounce = false
end
end
end
end
script.Parent.Touched:connect(onTouched)
-- Plasma Ball Expand & Dissipate
for i = 1, 15 do
script.Parent.Size = script.Parent.Size + Vector3.new(1, 1, 1)
wait()
end
wait(5)
for i = 1, 15 do
script.Parent.Size = script.Parent.Size + Vector3.new(-1, -1, -1)
wait()
end
script.Parent:remove()
Keep track of what things have been hit so far and check when hitting them if they’ve already been hit:
...
local hitParts = {}
function onTouched(hit)
--Return early, effectively doing nothing, if the "hit" part has already been processed
if hitParts[hit] then return end
hitParts[hit] = true --Using an Instance as a key in a dictionary is totally normal and OK, and really handy in this case. Read the Lua manual for more info of Lua dictionaries/associative arrays
--Could use a list and do if table.find(hitParts, hit) + table.insert(hitParts, hit), but dictionary is *probably* faster
...
This won’t prevent a Humanoid from taking damage several times though, because each Humanoid has several corresponding Parts. You can use the same technique to fix this. Just have another dictionary called hitHumanoids and manage it in the same way
Thank you in advance, this works well! The single bombs themselves don’t apply the parts that haven’t already been hit. But I have an issue. Since the bomb is being duplicated by a “spawner” script, when another bomb hits a part it applies the values again, how would I prevent other bombs from interacting from the already hit parts from other bombs?
Thanks again, really appreciate the advice and I will definitely look into the Lua Manual
Another approach is needed then. You’ll have to either centralize the information to the bomb spawner script (assuming there’s only one, i.e. it’s a singleton), or change it to be the affected things that keep track of what effects they have applied. With the former approach each bomb can ask the bomb spawner “has any bomb already hit this part?”. With the latter, each bomb can ask the hit part “have you already been hit by any bomb?”.
The latter is simpler because you only have to modify the bomb script, to something like this:
...
function onTouched(hit: BasePart)
if hit:GetAttribute("HasBeenHitByBomb") then return end
hitParts:SetAttribute("HasBeenHitByBomb", true)
...
Sorry to be a pain, but how would I implement this into my spawner script? Here is how my spawner script is currently set up:
local ServerStorage = game:GetService("ServerStorage")
local range = 35
Killbot = script.Parent
wait(16.5)
while true do
local b = ServerStorage.PlasmaBombPart:clone()
b.Parent = game.Workspace
b.Name = "Plasma Bomb"
b.CanCollide = true
b.Position = script.Parent.Position + Vector3.new(math.random(-range,range),math.random(-range,range),math.random(-range,range))
wait(5)
end
You’d need an interface that each bomb script can use to talk to the bomb spawner. Bombs need to ask the bomb spawner if a part has been hit, and also to tell the bomb spawner that something has just been hit, so I’d use a BindableFunction called “GetHasPartBeenHit” and a BindableEvent called “SetHasPartBeenHit”. Add this to the bomb spawner script above the infinite loop:
local hitParts = setmetatable({}, {__mode="k"})
script.GetHasPartBeenHit.OnInvoke = function(part:BasePart): boolean
return not not hitParts[part] -not not makes nil into false
end
script.SetHasPartBeenHit.Event:Connect(function(part:BasePart)
hitParts[part] = true
end)
Then in the bomb script you can do
...
function onTouched(hit: BasePart)
if bombSpawner.GetHasPartBeenHit.Invoke(hit) then return end
bombSpawner.SetHasPartBeenHit:Fire(hit)
...
Although I wouldn’t use BindableEvents/BindableFunctions in my own code, I usually prefer ModuleScripts
Sorry to waste your time, but I have ended up finding a very simple solution!
What I ended up doing was adding to the already long list of part checking to check if the part name equalled “PlasmaPart” and added in the list of things to do is to rename the parts ‘hit’ collides with to “PlasmaPart” as seen here:
function onTouched(hit)
if hit:IsA("Part") and hit.Name ~= "HumanoidRootPart" and hit.CollisionGroup ~= "Bombs&Coins" and hit.Name ~= "PlasmaPart" or hit:IsA("WedgePart") and hit.Name ~= "PlasmaPart" then
hit.Name = "PlasmaPart"
hit.BrickColor = script.Parent.BrickColor
hit.Material = "Granite"
hit.Reflectance = 0.2
hit.Transparency = 0.2
script.Parent.PlasmaHurtPlayer:Clone().Parent = hit
script.Parent.PlasmaHurtPlayer.Disabled = false
Again sorry for wasting your time, but I will certainly look more into the Lua Manual after seeing your advice