I’m trying to make a dice bomb for my game, but I’ve come across an issue. The way it works is, the dice rolls, the number it lands on is calculated by one function, then it explodes. Here’s the thing, the cooldown will be increased depending on the number the dice rolled on, this occurs in the return keyword at the last line of the code, where the extra cooldown time is equal to 5 * (diceRolledNumber / 0.25).
And so, when I try to add the bombData.cooldown number to the “now set” extraCooldownTime variable, it says that I attempted to perform arithmetic (add) on the number and nil.
Bomb Script (Where the cooldown and other stats are managed)
--\\ Variables //--
local serverStorage = game:GetService("ServerStorage")
local bombModule = require(serverStorage:WaitForChild("GameModules"):WaitForChild("Weapons"):WaitForChild("BombModule"))
local activateBombRemote = script.Parent:WaitForChild("ActivateBomb") -- Checks when the bomb is activated on the client.
local tool = script.Parent
local bombHandle = tool:WaitForChild("Handle")
local cooldown = false
local bombData = { -- This is the data for the bomb that are transfered into the explosion function when inherited.
damage = 8;
cooldown = 5;
blastPower = 100;
range = {
["L"] = 8;
["W"] = 8;
["H"] = 8;
};
tickTime = 2;
tickSound = bombHandle:WaitForChild("diceRoll").SoundId;
tickSoundVolume = 1;
explosionSoundId = bombHandle:WaitForChild("diceExplosion").SoundId;
explosionSoundVolume = 1.25;
explosionParticles = bombHandle.Explosion;
}
--\\ Functions //--
activateBombRemote.OnServerEvent:Connect(function(user)
if not cooldown then
cooldown = true
local bombClone = bombHandle:Clone() -- The cloned version of the handle that eventually explodes.
bombClone.Parent = game.Workspace
bombClone.CanCollide = true
bombClone.CFrame = bombHandle.CFrame * CFrame.new(0, 2, 2) -- The offset for the bomb's position when spawned.
local newBomb = bombModule.createBomb() -- Inherites the bomb functions.
newBomb.bombType = "Dice"
local extraCooldownTime : NumberValue
extraCooldownTime = newBomb:Explode(user, bombData, bombClone, false, true) -- the bomb explodes (vine boom).
task.wait(bombData.cooldown + extraCooldownTime) -- ***********errors here.**********
cooldown = false
return false
end
end)
Bomb Module (Where the bomb can explode and everything related to it functioning is there)
bomb.Dice = function(user, bombData, bombClone, plant, debugMode)
debugMode = true -- CHANGE THIS WHEN YOU ARE DONE MESSIAHAYAYYAHW!!
bombClone:SetNetworkOwnershipAuto(nil)
bombClone:ApplyImpulse(Vector3.new(-50, 0, 0)) -- Rolls the dice
bombClone:SetNetworkOwnershipAuto(user)
local diceRollSound : Sound = bombClone.diceRoll -- Plays the dice rolling sound
diceRollSound:Play()
local diceRotationTable = { -- A table that contains the values for the possible x, y, and/or z rotations of the dice depending on where the dice lands
[1] = Vector3.new(0, 0, 0),
[2] = Vector3.new(90, 0, 0),
[3] = Vector3.new(0, 0, -90),
[4] = Vector3.new(0, 0, 90),
[5] = Vector3.new(-90, 0, 0),
[6] = Vector3.new(0, 180, 180)
}
local diceRolledNumber : number -- The number that the dice rolled on.
local function getDiceNumber() -- Calculates which number the dice rolled on by rotation values in the rotationTable and the bombOrientation.
local bombOrientation = bombClone.Orientation
for index, value in pairs(diceRotationTable) do
if bombOrientation == value + Vector3.new(0, bombOrientation.Y, 0) then diceRolledNumber = 1 break end
if bombOrientation == value + Vector3.new(0, bombOrientation.Y, bombOrientation.Z) then diceRolledNumber = 2 break end
if bombOrientation == value + Vector3.new(bombOrientation.X, bombOrientation.Y, 0) then diceRolledNumber = 3 break end
if bombOrientation == value + Vector3.new(bombOrientation.X, bombOrientation.Y, 0) then diceRolledNumber = 4 break end
if bombOrientation == value + Vector3.new(0, bombOrientation.Y, bombOrientation.Z) then diceRolledNumber = 5 break end
if bombOrientation == value + Vector3.new(bombOrientation.X, 0, 0) then diceRolledNumber = 6 end
end
end
local diceNumberAssetIds = { -- The asset ids for another group of meshes that display what the user got, but ignore this for now because it will probably be changed into a number.
[1] = 15997437805,
[2] = 15997437576,
[3] = 15997437372,
[4] = 15997437174,
[5] = 15997437020,
[6] = 15997436868
} -- ignore
local diceNumberMesh = Instance.new("Part")
diceNumberMesh.Anchored = true
diceNumberMesh.CanCollide = false
local function displayDiceNumber(number) -- ignore this entire function
if number == 1 then
local specialMesh = Instance.new("SpecialMesh")
local meshLoadedIn = insertService:LoadAsset(diceNumberAssetIds[1])["Meshes/Dice"..tostring(number)]
specialMesh.MeshId = meshLoadedIn.MeshId
specialMesh.Parent = diceNumberMesh
meshLoadedIn.Parent:Destroy()
diceNumberMesh.BrickColor = BrickColor.new("Dusty Rose")
diceNumberMesh.Material = Enum.Material.Neon
diceNumberMesh.CFrame = bombClone.CFrame * CFrame.new(0, 5, 0)
diceNumberMesh.Parent = workspace.Terrain:FindFirstChild("Effects")
local meshSpinScript = bombClone.diceMeshSpin:Clone() -- A script inside of the diceHandle that causes the mesh to spin
meshSpinScript.Parent = diceNumberMesh
meshSpinScript.Enabled = true
elseif number == 6 then
local specialMesh = Instance.new("SpecialMesh")
local meshLoadedIn = insertService:LoadAsset(diceNumberAssetIds[6])["Meshes/Dice"..tostring(number)]
specialMesh.MeshId = meshLoadedIn.MeshId
specialMesh.Parent = diceNumberMesh
meshLoadedIn.Parent:Destroy()
diceNumberMesh.BrickColor = BrickColor.new("Shamrock")
diceNumberMesh.Material = Enum.Material.Neon
diceNumberMesh.CFrame = bombClone.CFrame * CFrame.new(0, 5, 0)
diceNumberMesh.Parent = workspace.Terrain:FindFirstChild("Effects")
local meshSpinScript = bombClone.diceMeshSpin:Clone() -- A script inside of the diceHandle that causes the mesh to spin
meshSpinScript.Parent = diceNumberMesh
meshSpinScript.Enabled = true
else
local specialMesh = Instance.new("SpecialMesh")
local meshLoadedIn = insertService:LoadAsset(diceNumberAssetIds[number])["Meshes/Dice"..tostring(number)]
specialMesh.MeshId = meshLoadedIn.MeshId
specialMesh.Parent = diceNumberMesh
meshLoadedIn.Parent:Destroy()
diceNumberMesh.BrickColor = BrickColor.new("Medium stone grey")
diceNumberMesh.Material = Enum.Material.Neon
diceNumberMesh.CFrame = bombClone.CFrame * CFrame.new(0, 5, 0)
diceNumberMesh.Parent = workspace.Terrain:FindFirstChild("Effects")
local meshSpinScript = bombClone.diceMeshSpin:Clone() -- A script inside of the diceHandle that causes the mesh to spin
meshSpinScript.Parent = diceNumberMesh
meshSpinScript.Enabled = true
end
end -- ignore
local diceNumberMeshTween = tweenService:Create( -- ignore
diceNumberMesh,
TweenInfo.new(1, Enum.EasingStyle.Quad, Enum.EasingDirection.In, 0, false, 0), {
Transparency = 1
}
) -- ignore
task.wait(1.5)
bombClone.AssemblyAngularVelocity = Vector3.new(0, 0, 0) -- Stops the dice from rolling
bombClone.Orientation = Vector3.new(math.round(bombClone.Orientation.X), math.round(bombClone.Orientation.Y), math.round(bombClone.Orientation.Z)) -- rounds up the orientation
-- and then it calculates the current dice number
getDiceNumber()
repeat task.wait() until diceRolledNumber ~= nil -- waits until diceRolledNumber is not nil
displayDiceNumber(diceRolledNumber) -- the mesh function, ignore.
bombData.damage *= diceRolledNumber -- Multiplies the damage by the number rolled.
bombData.blastPower += (diceRolledNumber * 0.25) * bombData.blastPower -- Increases the blastPower depending on the diceRolledNumber.
for rangeValues, value in pairs(bombData.range) do value += (diceRolledNumber * 0.15) * 8 end -- Inceases the range depending on the diceRolledNumber.
local diceRollResultSound = bombClone.diceRollResult:Clone() -- Plays the sound when the result is displayed, will probably get tweaked.
diceRollResultSound.Parent = diceNumberMesh -- ignore
diceRollResultSound:Play()
diceNumberMeshTween:Play() -- ignore
task.spawn(function() -- Destroys the sound and tween when they are done playing/tweening.
diceRollResultSound.Ended:Connect(function()
diceRollResultSound:Destroy()
end)
diceNumberMeshTween.Completed:Connect(function()
diceNumberMesh:Destroy()
end)
end)
task.wait(2)
task.spawn(function() -- Makes the dice explode.
local explosionClone = explosionParticles(bombClone, bombData)
local explosionSoundClone = Instance.new("Sound")
explosionSoundClone.SoundId = bombData.explosionSoundId
explosionSoundClone.Parent = bombClone
explosionSoundClone:Play()
task.spawn(function() explosionSoundClone.Ended:Connect(function() explosionSoundClone:Destroy() end) end)
bombClone.Transparency = 1
local region3 = Region3.new(
bombClone.Position - Vector3.new(bombData.range.L, bombData.range.H, bombData.range.W),
bombClone.Position + Vector3.new(bombData.range.L, bombData.range.H, bombData.range.W) -- Makes a square that is 5x5 long and wide, and 10 Tix high (hence the 1 to 10)
) -- Creates a region3 that destroys any parts in the explosions radius.
local explosionVisualizer
if debugMode then explosionVisualizer = visualizerCalculator(region3) end
local explosion = Instance.new("Explosion") -- The explosion instance
explosion.Parent = bombClone
explosion.Visible = false
explosion.Position = bombClone.Position
explosion.BlastRadius = region3.Size.Z
explosion.BlastPressure = 0
explosion.DestroyJointRadiusPercent = 0
local appliedForcesOn = {} -- A table containing a list of objects that the force has already been applied on, preventing spam.
explosion.Hit:Connect(function(hit)
if hit.Parent:FindFirstChildOfClass("Humanoid") then -- For players
local char = hit.Parent
local rootPart = char:FindFirstChild("HumanoidRootPart")
local humanoid = hit.Parent:FindFirstChildOfClass("Humanoid")
blastPowerForce(rootPart, bombData, bombClone)
if appliedForcesOn[char] == nil and char.Name ~= user.Name then
appliedForcesOn[char] = char
humanoid:TakeDamage(bombData.damage)
end
end
end)
local overlapParams = OverlapParams.new()
if debugMode then overlapParams.FilterDescendantsInstances = {explosionVisualizer} end
local parts = workspace:GetPartBoundsInBox(region3.CFrame, region3.Size, overlapParams)
for i, v in pairs(parts) do
if v.Name == "Brick" then
for i, constraint in pairs(v:GetChildren()) do
if constraint:IsA("Constraint") then constraint:Destroy() end
end
v.Anchored = false
v.CanTouch = false
v.BrickColor = user.TeamColor
if not table.find(appliedForcesOn, v) then
local direction = (bombClone.Position - v.Position).Unit
v.AssemblyLinearVelocity = Vector3.new(-(direction.X * bombData.blastPower)/5, bombData.blastPower/5, -(direction.Z * bombData.blastPower)/5)
appliedForcesOn[v] = v -- Since for some reason most buildings get flung so far when the blast power is over 200, I decided to divide it by 5
end -- to minimize the effect of the buildings getting flung.
deleteTaggedBricks(v)
elseif v.Name == "GameBrick" then v.Name = "TaggedGameBrick" -- TaggedGameBricks are GameBricks in the game that have been effected by the bomb,
-- while regular Bricks are just bricks you can destroy by default.
for i, constraint in pairs(v:GetChildren()) do
if constraint:IsA("Constraint") then constraint:Destroy() end
end
v.Anchored = false
v.CanTouch = false
v.BrickColor = user.TeamColor
if not table.find(appliedForcesOn, v) then
local direction = (bombClone.Position - v.Position).Unit
v.AssemblyLinearVelocity = Vector3.new(-(direction.X * bombData.blastPower), bombData.blastPower, -(direction.Z * bombData.blastPower))
appliedForcesOn[v] = v
end
user.leaderstats.Bricks.Value += 1 -- The total bricks the player has broken throughout the round.
user["T. Bricks"].Value += 1 -- The total bricks that the player has destroyed throughout there playtime
user.leaderstats.Tix.Value += .1 -- Increases the players currency (Tix) by 0.1.
deleteTaggedBricks(v)
end
end
task.wait(1.25)
explosionClone.Enabled = false -- Disables the explosion particles.
debris:AddItem(bombClone, 5)
debris:AddItem(explosionVisualizer, 5)
explosionVisualizer = nil
table.clear(appliedForcesOn)
end)
return 5 * (diceRolledNumber / 0.25) -- returns an extra cooldown value depending on the number the dice rolled
end