Disaster Slap Tower
I have created the first 5 disasters for our obby tower trolling game Disaster Slap Tower, and I’m happy to present them and how I made them.
If you haven’t seen the previous blog, go ahead and check it out by clicking here.
Disasters
One of the biggest focuses this game has is having an large enough arsenal of disasters that our button can randomly select and call upon in order to keep the game fresh and fun, and this blog showcases the disasters we’ve made so far!
Ice Freeze
This event causes every single part in the Workspace to “freeze over”, making them slippery – just like ice!
This event is bound to make players slide into a lava brick by mistake, which just goes to show how prepared you have to be for these events, as one slip-up (literally) will mean you have to start all over!
This was especially difficult to get right, as I needed to come up with a system that would:
- Take a snapshot of all parts’ CustomPhysicalProperties prior to the event being called
- Then override all parts with my own set of CustomPhysicalProperties (in order to make them slippery)
- Finally, once the cooldown is over, I have to map every part to the CustomPhysicalProperties they originally possessed.
This took a fair bit of trial and error, but I came up with the following code to first save the original properties:
local Workspace = game:GetService("Workspace")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Settings = require(ReplicatedStorage:WaitForChild("EventSettings"))
-- Slippery physical settings: friction = 0, frictionWeight = 35
local SLIPPERY_PROPS = PhysicalProperties.new(0.7, 0, 0.5, 35, 0)
local RESTORE_DELAY = Settings.EventDuration
-- Stores original physical properties for each part
local originalPropsMap = {}
-- Take a snapshot of all basepart physics before applying changes
local function snapshotOriginalProps()
for _, part in ipairs(Workspace:GetDescendants()) do
if part:IsA("BasePart") then
if not originalPropsMap[part] then
local props = part.CustomPhysicalProperties
originalPropsMap[part] = props or false -- false = no custom props as a fallback if not editable
end
end
end
end
I then used a simple iteration using the similar conditions for the snapshot process to assign every eligible part the properties I created in SLIPPERY_PROPS
local function applySlippery()
for part, _ in pairs(originalPropsMap) do
if part and part:IsA("BasePart") then
part.CustomPhysicalProperties = SLIPPERY_PROPS
end
end
end
After that, I made another “for each” loop to check every part mapped in our originalPropsMap
and assign each part its original properties.
-- Revert all parts to their original physical properties
local function restoreOriginalProps()
for part, originalProps in pairs(originalPropsMap) do
if part and part:IsA("BasePart") then
if originalProps == false then
part.CustomPhysicalProperties = nil
else
part.CustomPhysicalProperties = originalProps
end
end
end
originalPropsMap = {}
end
This would all be wrapped up into the return function, and ready to be used in the game!
Low Gravity
Triggering this event will temporarily decrease the global gravity of the server, causing both players and ANY unanchored object to behave how you would imagine they might if they were on the moon!
This event changes quite a few interactions, namely with the propellor part and any player who may have bought the Gravity Coil gamepass.
The logic for this event was really straightforward and didn’t take long + it can be carried onto the High Speed event
All it involved was indexing through all players ingame, changing their JumpPower
, and changing the workspace gravity, and then changing it back after the delay.
local originalGravity = Workspace.Gravity
local lowGravity = 100
local jumpPower = 22
local function applyLowGravity()
Workspace.Gravity = lowGravity
for _,players in pairs(game.Players:GetChildren()) do
players.Character.Humanoid.JumpHeight = jumpPower
end
print("[LowGravityEvent] Gravity lowered to", lowGravity, "for", duration, "seconds.")
task.delay(duration, function()
Workspace.Gravity = originalGravity
for _,players in pairs(game.Players:GetChildren()) do
players.Character.Humanoid.JumpHeight = 7.2
end
print("[LowGravityEvent] Gravity reset to", originalGravity)
end)
end
High Speed
This event is probably just as self explanatory as the low gravity one.
This event causes all players to move at more than double their normal player speed. The troll potential for this is HUGE!
If a player is unfortunate enough to get caught with this event while attempting a parkour jump onto a slim platform, they might severely “overestimate” their jump (though not their fault) and plummet all the way back down!
Tsunami
This is definitely one of the most brutal random event we’ve added yet.
This one was more so designed to punish the button presser more than the actual players attempting to complete the obby.
This event will cause a tsunami to rip through the bottom stage (where the button is located) and vanquish any players who stand in its path.
If your reaction times are quick enough, you might just climb high enough to avoid its destruction.
The way I made this was by 3D modelling a simple tsunami mesh which I could import to Roblox as a .fbx file into Asset Manager, which I then coloured blue and made slightly transparent.

I then added a foam particle emitter at the top of the wave, and some bubble particle emitters inside of the actual mesh, and a sound emitter just to make it clear to anyone seeing this that it is in fact a tsunami coming to eliminate you!
Anvil Rain
Quick! Did you check the forecast? I heard it was raining… anvils???
Yup, you heard that right. We added an onslaught of anvils that will squish the player into a thin pancake if hit.
This was really fun to make, and even funner to test!

Informing The Players
We’ve got all these events so far, but the players have NO clue that they’re happening! We need to make an alert that tells them what event is coming in order to give them an idea of what they’re up against!
I came up with a simple LocalScript under a GUI I put in StarterGUI that would show a custom alert dependant on which ModuleScript is called, which I customised to my liking and did a bit of tween work just smooth the fade transition from in and out.
local TweenService = game:GetService("TweenService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local gui = script.Parent
local label = gui:WaitForChild("EventLabel")
local stroke = label:FindFirstChildOfClass("UIStroke")
local sound = gui:FindFirstChild("EventSound")
local remote = ReplicatedStorage:WaitForChild("ShowEventUI")
label.TextXAlignment = Enum.TextXAlignment.Center
label.TextYAlignment = Enum.TextYAlignment.Center
label.TextScaled = true
local eventNames = {
AnvilEvent = "⛏️ Anvil Rain! 🔨",
LowGravityEvent = "🌠 Low Gravity! 🪐",
HighSpeedEvent = "🏃 High Speed Event! ⚡",
TsunamiEvent = "🌊 Tsunami Incoming! Get to high ground! 🌊",
SlipperyEvent = "❄️ Ice event! Everything is slippery! ❄️",
}
This was the final result, which I’m really proud of!

Surprise…?
We’ve got a surprise planned for our next blog, so stay tuned to see what we’ll reveal…