
KeylessUniversal

local RunService = game:GetService("RunService")
local PathfindingService = game:GetService("PathfindingService")
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local ActiveDisasterType = "Tornado"
local ActiveStorms = {}
local Settings = {
SpawnPlacement = "Original",
WanderSpeed = 25,
Color_R = 100,
Color_G = 100,
Color_B = 105,
FunnelTrans = 0.6,
DebrisDensity = 100,
DebrisVis = 0.8,
EF_Level = 0,
PhysicsMode = "Original",
TornadoShape = "Classic",
LiftSpeed = 1.0,
RotationSpeed = 1.0,
RadiusMult = 1.0,
PullStrengthMult = 1.0,
MobileButtonPosition = "Top-Right"
}
local EF_STATS = {
[-1] = {Radius = 25, Strength = 15, Height = 70, Scale = 0.4},
[0] = {Radius = 40, Strength = 25, Height = 100, Scale = 0.6},
[1] = {Radius = 60, Strength = 40, Height = 150, Scale = 1},
[2] = {Radius = 100, Strength = 70, Height = 220, Scale = 1.6},
[3] = {Radius = 160, Strength = 120, Height = 320, Scale = 2.4},
[4] = {Radius = 240, Strength = 200, Height = 450, Scale = 3.5},
[5] = {Radius = 350, Strength = 320, Height = 600, Scale = 5.0}
}
local ScreenGui = Instance.new("ScreenGui", Player:WaitForChild("PlayerGui"))
ScreenGui.Name = "StormOS_V8_Merged"
ScreenGui.ResetOnSpawn = false
local ChangelogFrame = Instance.new("Frame", ScreenGui)
ChangelogFrame.AnchorPoint = Vector2.new(0.5, 0.5)
ChangelogFrame.Size = UDim2.new(0.45, 0, 0.5, 0)
ChangelogFrame.Position = UDim2.new(0.5, 0, 0.5, 0)
ChangelogFrame.BackgroundColor3 = Color3.fromRGB(15, 15, 18)
ChangelogFrame.Visible = true
Instance.new("UICorner", ChangelogFrame).CornerRadius = UDim.new(0, 12)
Instance.new("UIStroke", ChangelogFrame).Color = Color3.fromRGB(80, 140, 255)
local CL_Title = Instance.new("TextLabel", ChangelogFrame)
CL_Title.Size = UDim2.new(1, 0, 0.1, 0)
CL_Title.Text = "STORM OS v8.0 - CHANGELOG"
CL_Title.Font = Enum.Font.GothamBlack
CL_Title.TextColor3 = Color3.new(1, 1, 1)
CL_Title.TextSize = 20
CL_Title.TextScaled = true
CL_Title.BackgroundTransparency = 1
local CL_CloseBtn = Instance.new("TextButton", ChangelogFrame)
CL_CloseBtn.Size = UDim2.new(0, 30, 0, 30)
CL_CloseBtn.Position = UDim2.new(1, -35, 0, 5)
CL_CloseBtn.Text = "X"
CL_CloseBtn.BackgroundColor3 = Color3.fromRGB(180, 50, 50)
CL_CloseBtn.TextColor3 = Color3.new(1, 1, 1)
CL_CloseBtn.Font = Enum.Font.GothamBold
CL_CloseBtn.TextScaled = true
Instance.new("UICorner", CL_CloseBtn).CornerRadius = UDim.new(0, 6)
local CL_Scroll = Instance.new("ScrollingFrame", ChangelogFrame)
CL_Scroll.Size = UDim2.new(1, -20, 0.8, 0)
CL_Scroll.Position = UDim2.new(0, 10, 0.15, 0)
CL_Scroll.BackgroundColor3 = Color3.fromRGB(22, 22, 26)
CL_Scroll.ScrollBarThickness = 3
CL_Scroll.CanvasSize = UDim2.new(0, 0, 0, 0)
Instance.new("UICorner", CL_Scroll)
local CL_Layout = Instance.new("UIListLayout", CL_Scroll)
CL_Layout.Padding = UDim.new(0, 10)
CL_Layout.HorizontalAlignment = Enum.HorizontalAlignment.Center
CL_Layout.SortOrder = Enum.SortOrder.LayoutOrder
local ChangelogEntries = {
{
Date = os.date("%Y-%m-%d %H:%M:%S"),
Text = "Max 2 tornadoes – SPAWN creates first, SPAWN ADDITIONAL adds second. Mobile button positionable."
},
{
Date = "2026-05-24 18:30",
Text = "Tornado physics improved – player & held tools excluded from pull."
},
{
Date = "2026-05-23 09:15",
Text = "Initial V8 merge – tornado visual overhaul & responsive GUI."
}
}
for i, entry in ipairs(ChangelogEntries) do
local entryFrame = Instance.new("Frame", CL_Scroll)
entryFrame.Size = UDim2.new(0.95, 0, 0, 45)
entryFrame.BackgroundTransparency = 1
local dateLbl = Instance.new("TextLabel", entryFrame)
dateLbl.Size = UDim2.new(1, 0, 0.35, 0)
dateLbl.Text = "[" .. entry.Date .. "]"
dateLbl.Font = Enum.Font.GothamBold
dateLbl.TextColor3 = Color3.fromRGB(80, 140, 255)
dateLbl.TextSize = 12
dateLbl.BackgroundTransparency = 1
dateLbl.TextXAlignment = Enum.TextXAlignment.Left
local descLbl = Instance.new("TextLabel", entryFrame)
descLbl.Size = UDim2.new(1, 0, 0.65, 0)
descLbl.Position = UDim2.new(0, 0, 0.35, 0)
descLbl.Text = entry.Text
descLbl.Font = Enum.Font.Gotham
descLbl.TextColor3 = Color3.new(0.9, 0.9, 0.9)
descLbl.TextSize = 14
descLbl.BackgroundTransparency = 1
descLbl.TextXAlignment = Enum.TextXAlignment.Left
descLbl.TextWrapped = true
end
local LoadingFrame = Instance.new("Frame", ScreenGui)
LoadingFrame.Size = UDim2.new(1, 0, 1, 0)
LoadingFrame.BackgroundColor3 = Color3.fromRGB(0, 0, 0)
LoadingFrame.BackgroundTransparency = 0.3
LoadingFrame.Visible = false
LoadingFrame.ZIndex = 10
local LoadingLabel = Instance.new("TextLabel", LoadingFrame)
LoadingLabel.Size = UDim2.new(0.6, 0, 0.1, 0)
LoadingLabel.AnchorPoint = Vector2.new(0.5, 0.5)
LoadingLabel.Position = UDim2.new(0.5, 0, 0.4, 0)
LoadingLabel.Text = "Loading StormOS v8.0..."
LoadingLabel.Font = Enum.Font.GothamBlack
LoadingLabel.TextColor3 = Color3.new(1, 1, 1)
LoadingLabel.TextSize = 28
LoadingLabel.BackgroundTransparency = 1
LoadingLabel.TextScaled = true
local ProgressBar = Instance.new("Frame", LoadingFrame)
ProgressBar.Size = UDim2.new(0.4, 0, 0.03, 0)
ProgressBar.AnchorPoint = Vector2.new(0.5, 0.5)
ProgressBar.Position = UDim2.new(0.5, 0, 0.55, 0)
ProgressBar.BackgroundColor3 = Color3.fromRGB(40, 40, 45)
Instance.new("UICorner", ProgressBar)
local ProgressFill = Instance.new("Frame", ProgressBar)
ProgressFill.Size = UDim2.new(0, 0, 1, 0)
ProgressFill.BackgroundColor3 = Color3.fromRGB(80, 140, 255)
ProgressFill.BorderSizePixel = 0
Instance.new("UICorner", ProgressFill)
local ProgressText = Instance.new("TextLabel", ProgressBar)
ProgressText.Size = UDim2.new(1, 0, 1, 0)
ProgressText.Text = "0%"
ProgressText.Font = Enum.Font.GothamBold
ProgressText.TextColor3 = Color3.new(1, 1, 1)
ProgressText.TextSize = 14
ProgressText.BackgroundTransparency = 1
ProgressText.TextScaled = true
local MainFrame = Instance.new("Frame", ScreenGui)
MainFrame.AnchorPoint = Vector2.new(0.5, 0.5)
MainFrame.Size = UDim2.new(0.35, 0, 0.6, 0)
MainFrame.Position = UDim2.new(0.75, 0, 0.5, 0)
MainFrame.BackgroundColor3 = Color3.fromRGB(15, 15, 18)
MainFrame.Visible = false
MainFrame.Active = true
Instance.new("UICorner", MainFrame).CornerRadius = UDim.new(0, 12)
Instance.new("UIStroke", MainFrame).Color = Color3.fromRGB(80, 140, 255)
local dragging, dragStart, startPos
MainFrame.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
dragging = true
dragStart = input.Position
startPos = MainFrame.Position
input.Changed:Connect(function()
if input.UserInputState == Enum.UserInputState.End then dragging = false end
end)
end
end)
UserInputService.InputChanged:Connect(function(input)
if dragging and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
local delta = input.Position - dragStart
MainFrame.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y)
end
end)
local Title = Instance.new("TextLabel", MainFrame)
Title.Size = UDim2.new(0.5, 0, 0.08, 0)
Title.Text = "STORM OS v8.0"
Title.Position = UDim2.new(0, 10, 0, 0)
Title.Font = Enum.Font.GothamBlack
Title.TextColor3 = Color3.new(1, 1, 1)
Title.TextSize = 16
Title.TextScaled = true
Title.BackgroundTransparency = 1
Title.TextXAlignment = Enum.TextXAlignment.Left
local OpenBtn = Instance.new("TextButton", ScreenGui)
OpenBtn.Size = UDim2.new(0, 50, 0, 50)
OpenBtn.Text = "🌪️"
OpenBtn.TextSize = 28
OpenBtn.BackgroundColor3 = Color3.fromRGB(20, 20, 25)
OpenBtn.Visible = false
Instance.new("UICorner", OpenBtn).CornerRadius = UDim.new(1, 0)
Instance.new("UIStroke", OpenBtn).Color = Color3.fromRGB(80, 140, 255)
local CloseBtn = Instance.new("TextButton", MainFrame)
CloseBtn.Size = UDim2.new(0, 30, 0, 30)
CloseBtn.Position = UDim2.new(1, -35, 0, 5)
CloseBtn.Text = "X"
CloseBtn.BackgroundColor3 = Color3.fromRGB(180, 50, 50)
CloseBtn.TextColor3 = Color3.new(1, 1, 1)
CloseBtn.Font = Enum.Font.GothamBold
CloseBtn.TextScaled = true
Instance.new("UICorner", CloseBtn).CornerRadius = UDim.new(0, 6)
CloseBtn.MouseButton1Click:Connect(function()
MainFrame.Visible = false
OpenBtn.Visible = true
end)
OpenBtn.MouseButton1Click:Connect(function()
MainFrame.Visible = true
OpenBtn.Visible = false
end)
local ButtonPositions = {
["Top-Left"] = UDim2.new(0, 10, 0, 10),
["Top-Right"] = UDim2.new(1, -60, 0, 10),
["Bottom-Left"] = UDim2.new(0, 10, 1, -60),
["Bottom-Right"] = UDim2.new(1, -60, 1, -60),
["Center"] = UDim2.new(0.5, -25, 0.5, -25)
}
local function UpdateButtonPosition()
local pos = ButtonPositions[Settings.MobileButtonPosition]
if pos then
OpenBtn.Position = pos
end
end
UpdateButtonPosition()
local TabContainer = Instance.new("Frame", MainFrame)
TabContainer.Size = UDim2.new(1, -20, 0.07, 0)
TabContainer.Position = UDim2.new(0, 10, 0.08, 0)
TabContainer.BackgroundTransparency = 1
local TabLayout = Instance.new("UIListLayout", TabContainer)
TabLayout.FillDirection = Enum.FillDirection.Horizontal
TabLayout.Padding = UDim.new(0, 5)
local ContentArea = Instance.new("Frame", MainFrame)
ContentArea.Size = UDim2.new(1, -20, 0.8, 0)
ContentArea.Position = UDim2.new(0, 10, 0.17, 0)
ContentArea.BackgroundColor3 = Color3.fromRGB(22, 22, 26)
Instance.new("UICorner", ContentArea)
local Tabs = {}
local function CreateTab(name)
local btn = Instance.new("TextButton", TabContainer)
btn.Size = UDim2.new(0.31, 0, 1, 0)
btn.Text = name
btn.BackgroundColor3 = Color3.fromRGB(30, 30, 35)
btn.TextColor3 = Color3.new(0.7, 0.7, 0.7)
btn.Font = Enum.Font.GothamBold
btn.TextSize = 12
btn.TextScaled = true
Instance.new("UICorner", btn)
local frame = Instance.new("ScrollingFrame", ContentArea)
frame.Size = UDim2.new(1, -10, 1, -10)
frame.BackgroundTransparency = 1
frame.Position = UDim2.new(0, 5, 0, 5)
frame.ScrollBarThickness = 2
frame.Visible = false
frame.CanvasSize = UDim2.new(0, 0, 2, 0)
local layout = Instance.new("UIListLayout", frame)
layout.Padding = UDim.new(0, 8)
layout.HorizontalAlignment = Enum.HorizontalAlignment.Center
btn.MouseButton1Click:Connect(function()
for _, t in pairs(Tabs) do
t.Btn.BackgroundColor3 = Color3.fromRGB(30, 30, 35)
t.Btn.TextColor3 = Color3.new(0.7, 0.7, 0.7)
t.Frame.Visible = false
end
btn.BackgroundColor3 = Color3.fromRGB(80, 140, 255)
btn.TextColor3 = Color3.new(1, 1, 1)
frame.Visible = true
end)
table.insert(Tabs, {Btn = btn, Frame = frame})
return frame
end
local TabControl = CreateTab("CONTROL")
local TabPhysics = CreateTab("PHYSICS")
local TabVisuals = CreateTab("VISUALS")
local function CreateSetting(parent, text, settingKey, min, max, step)
local row = Instance.new("Frame", parent)
row.Size = UDim2.new(0.95, 0, 0, 35)
row.BackgroundTransparency = 1
local lbl = Instance.new("TextLabel", row)
lbl.Size = UDim2.new(0.5, 0, 1, 0)
lbl.Text = text
lbl.TextColor3 = Color3.new(0.9, 0.9, 0.9)
lbl.BackgroundTransparency = 1
lbl.Font = Enum.Font.Gotham
lbl.TextXAlignment = Enum.TextXAlignment.Left
lbl.TextScaled = true
local valLbl = Instance.new("TextLabel", row)
valLbl.Size = UDim2.new(0.2, 0, 1, 0)
valLbl.Position = UDim2.new(0.5, 0, 0, 0)
valLbl.Text = tostring(Settings[settingKey])
valLbl.BackgroundTransparency = 1
valLbl.TextColor3 = Color3.fromRGB(80, 140, 255)
valLbl.Font = Enum.Font.GothamBold
valLbl.TextScaled = true
local minus = Instance.new("TextButton", row)
minus.Size = UDim2.new(0, 25, 0, 25)
minus.Position = UDim2.new(0.75, 0, 0.5, -12)
minus.Text = "-"
minus.BackgroundColor3 = Color3.fromRGB(40, 40, 45)
minus.TextColor3 = Color3.new(1, 1, 1)
minus.Font = Enum.Font.GothamBold
Instance.new("UICorner", minus)
local plus = Instance.new("TextButton", row)
plus.Size = UDim2.new(0, 25, 0, 25)
plus.Position = UDim2.new(0.9, 0, 0.5, -12)
plus.Text = "+"
plus.BackgroundColor3 = Color3.fromRGB(40, 40, 45)
plus.TextColor3 = Color3.new(1, 1, 1)
plus.Font = Enum.Font.GothamBold
Instance.new("UICorner", plus)
local function update(change)
Settings[settingKey] = math.clamp(Settings[settingKey] + change, min, max)
valLbl.Text = tostring(math.floor(Settings[settingKey] * 10) / 10)
if settingKey == "Color_R" or settingKey == "Color_G" or settingKey == "Color_B" or settingKey == "FunnelTrans" or settingKey == "DebrisVis" then
UpdateVisuals()
end
end
minus.MouseButton1Click:Connect(function() update(-step) end)
plus.MouseButton1Click:Connect(function() update(step) end)
end
local function CreateDropdown(parent, text, settingKey, options)
local row = Instance.new("Frame", parent)
row.Size = UDim2.new(0.95, 0, 0, 35)
row.BackgroundTransparency = 1
local lbl = Instance.new("TextLabel", row)
lbl.Size = UDim2.new(0.5, 0, 1, 0)
lbl.Text = text
lbl.TextColor3 = Color3.new(0.9, 0.9, 0.9)
lbl.BackgroundTransparency = 1
lbl.Font = Enum.Font.Gotham
lbl.TextXAlignment = Enum.TextXAlignment.Left
lbl.TextScaled = true
local dropBtn = Instance.new("TextButton", row)
dropBtn.Size = UDim2.new(0.45, 0, 0.8, 0)
dropBtn.Position = UDim2.new(0.5, 0, 0.1, 0)
dropBtn.Text = Settings[settingKey]
dropBtn.BackgroundColor3 = Color3.fromRGB(40, 40, 45)
dropBtn.TextColor3 = Color3.new(1, 1, 1)
dropBtn.Font = Enum.Font.GothamBold
dropBtn.TextScaled = true
Instance.new("UICorner", dropBtn)
local currentIndex = 1
for i, opt in ipairs(options) do
if opt == Settings[settingKey] then
currentIndex = i
break
end
end
dropBtn.MouseButton1Click:Connect(function()
currentIndex = currentIndex + 1
if currentIndex > #options then currentIndex = 1 end
Settings[settingKey] = options[currentIndex]
dropBtn.Text = options[currentIndex]
if settingKey == "MobileButtonPosition" then
UpdateButtonPosition()
end
end)
end
local function CreateActionBtn(parent, text, color, callback)
local b = Instance.new("TextButton", parent)
b.Size = UDim2.new(0.95, 0, 0, 40)
b.BackgroundColor3 = color
b.Text = text
b.Font = Enum.Font.GothamBold
b.TextColor3 = Color3.new(1, 1, 1)
b.TextSize = 14
b.TextScaled = true
Instance.new("UICorner", b)
b.MouseButton1Click:Connect(callback)
return b
end
local function BuildUI_For_Disaster()
TabControl:ClearAllChildren()
TabPhysics:ClearAllChildren()
TabVisuals:ClearAllChildren()
Instance.new("UIListLayout", TabControl).Padding = UDim.new(0, 8)
Instance.new("UIListLayout", TabPhysics).Padding = UDim.new(0, 8)
Instance.new("UIListLayout", TabVisuals).Padding = UDim.new(0, 8)
-- SPAWN TORNADO: only if none exist
CreateActionBtn(TabControl, "SPAWN TORNADO", Color3.fromRGB(40, 180, 80), function()
if #ActiveStorms == 0 then
GenerateDisaster()
end
end)
-- SPAWN ADDITIONAL: only if exactly 1 exists → total becomes 2
CreateActionBtn(TabControl, "SPAWN ADDITIONAL", Color3.fromRGB(150, 100, 40), function()
if #ActiveStorms == 1 then
GenerateDisaster()
end
end)
CreateActionBtn(TabControl, "CLEAR ALL", Color3.fromRGB(180, 50, 50), function() DestroyDisaster() end)
CreateDropdown(TabControl, "Spawn Placement", "SpawnPlacement", {"Original", "Infront"})
CreateSetting(TabControl, "Wander AI Speed", "WanderSpeed", 0, 100, 5)
CreateSetting(TabControl, "EF Level (-1=EFU)", "EF_Level", -1, 5, 1)
CreateDropdown(TabControl, "Tornado Shape", "TornadoShape", {"Classic", "Rope", "Wedge"})
CreateDropdown(TabPhysics, "Vortex Mode", "PhysicsMode", {"Original", "Better"})
CreateSetting(TabPhysics, "Pull Radius Mult", "RadiusMult", 0.5, 3.0, 0.1)
CreateSetting(TabPhysics, "Suck Strength Mult", "PullStrengthMult", 0.5, 5.0, 0.1)
CreateSetting(TabPhysics, "Updraft Lift Speed", "LiftSpeed", 0.5, 3.0, 0.1)
CreateSetting(TabPhysics, "Rotation Speed Mult", "RotationSpeed", 0.1, 5.0, 0.2)
CreateSetting(TabVisuals, "Cloud Transp.", "FunnelTrans", 0.1, 1.0, 0.1)
CreateSetting(TabVisuals, "Debris Visibility", "DebrisVis", 0.0, 1.0, 0.1)
CreateSetting(TabVisuals, "Debris Density", "DebrisDensity", 0, 500, 50)
CreateSetting(TabVisuals, "Color: Red", "Color_R", 0, 255, 15)
CreateSetting(TabVisuals, "Color: Green", "Color_G", 0, 255, 15)
CreateSetting(TabVisuals, "Color: Blue", "Color_B", 0, 255, 15)
CreateDropdown(TabVisuals, "Mobile Button Pos", "MobileButtonPosition",
{"Top-Left", "Top-Right", "Bottom-Left", "Bottom-Right", "Center"})
Tabs[1].Btn.BackgroundColor3 = Color3.fromRGB(80, 140, 255)
Tabs[1].Btn.TextColor3 = Color3.new(1, 1, 1)
TabControl.Visible = true
end
CL_CloseBtn.MouseButton1Click:Connect(function()
ChangelogFrame.Visible = false
LoadingFrame.Visible = true
task.spawn(function()
local duration = 20
local startTime = tick()
while true do
local elapsed = tick() - startTime
local percent = math.min(100, math.floor((elapsed / duration) * 100))
ProgressFill.Size = UDim2.new(percent/100, 0, 1, 0)
ProgressText.Text = percent .. "%"
if elapsed >= duration then break end
task.wait(0.1)
end
LoadingFrame.Visible = false
BuildUI_For_Disaster()
MainFrame.Visible = true
OpenBtn.Visible = true
UpdateButtonPosition()
end)
end)
function UpdateVisuals()
local col = Color3.fromRGB(Settings.Color_R, Settings.Color_G, Settings.Color_B)
for _, stormData in ipairs(ActiveStorms) do
if stormData.Emitter then
stormData.Emitter.Rate = Settings.DebrisDensity
stormData.Emitter.Color = ColorSequence.new(col)
local t = math.clamp(1 - Settings.DebrisVis, 0, 1)
stormData.Emitter.Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0, t), NumberSequenceKeypoint.new(1, 1)})
end
for _, data in ipairs(stormData.Segments) do
if data.Part then
data.Part.Color = col
data.Part.Transparency = Settings.FunnelTrans
end
end
end
end
local function isDescendantOfPlayerCharacter(part)
local ancestor = part.Parent
while ancestor do
if ancestor:IsA("Model") and ancestor:FindFirstChild("Humanoid") then
local player = Players:GetPlayerFromCharacter(ancestor)
if player then
return true
end
end
ancestor = ancestor.Parent
end
return false
end
function GenerateDisaster()
local StormID = tick()
local DisasterModel = Instance.new("Model", workspace)
DisasterModel.Name = "Tornado_" .. math.floor(StormID)
local Core = Instance.new("Part", DisasterModel)
Core.Anchored = true
Core.CanCollide = false
Core.Transparency = 1
if Settings.SpawnPlacement == "Infront" and Player.Character and Player.Character:FindFirstChild("HumanoidRootPart") then
local rootPart = Player.Character.HumanoidRootPart
Core.Position = rootPart.Position + (rootPart.CFrame.LookVector * 200) + Vector3.new(0, 5, 0)
else
Core.Position = Vector3.new(0, 5, 0)
end
DisasterModel.PrimaryPart = Core
local attach = Instance.new("Attachment", Core)
local StormData = {
Model = DisasterModel,
Core = Core,
Emitter = nil,
Segments = {},
Path = {},
Waypoint = 1,
Active = true,
NextScan = 0,
CachedParts = {}
}
table.insert(ActiveStorms, StormData)
task.spawn(function()
local stats = EF_STATS[Settings.EF_Level]
local segments = 20 + (Settings.EF_Level * 5)
local DebrisEmitter = Instance.new("ParticleEmitter", attach)
DebrisEmitter.Texture = "rbxassetid://258128463"
DebrisEmitter.Size = NumberSequence.new({NumberSequenceKeypoint.new(0, 10), NumberSequenceKeypoint.new(1, 80)})
DebrisEmitter.Lifetime = NumberRange.new(3, 6)
DebrisEmitter.Speed = NumberRange.new(20, 50)
DebrisEmitter.SpreadAngle = Vector2.new(360, 360)
DebrisEmitter.Drag = 2
DebrisEmitter.Acceleration = Vector3.new(0, 40, 0)
DebrisEmitter.RotSpeed = NumberRange.new(-300, 300)
DebrisEmitter.EmissionDirection = Enum.NormalId.Top
StormData.Emitter = DebrisEmitter
for i = 1, segments do
local p = Instance.new("Part")
p.Shape = Enum.PartType.Cylinder
p.Anchored = true
p.CanCollide = false
local ratio = i / segments
local width = (Settings.TornadoShape == "Rope" and (2 + (ratio ^ 3) * (40 * stats.Scale))) or
(Settings.TornadoShape == "Wedge" and (20 + (ratio ^ 1.5) * (300 * stats.Scale))) or
(5 + (ratio ^ 3) * (120 * stats.Scale))
p.Size = Vector3.new((stats.Height/segments) * 1.5, width, width)
p.Parent = DisasterModel
table.insert(StormData.Segments, {Part = p, Height = i * (stats.Height/segments), Speed = 15 * (1.2 - ratio), IsHurricane = false})
end
UpdateVisuals()
end)
task.spawn(function()
while StormData.Active do
local target = Core.Position + Vector3.new(math.random(-500, 500), 0, math.random(-500, 500))
local path = PathfindingService:CreatePath({AgentRadius = 10})
path:ComputeAsync(Core.Position, target)
if path.Status == Enum.PathStatus.Success then
StormData.Path = path:GetWaypoints()
StormData.Waypoint = 1
end
task.wait(8)
end
end)
end
function DestroyDisaster()
for _, storm in ipairs(ActiveStorms) do
storm.Active = false
if storm.Model then storm.Model:Destroy() end
end
table.clear(ActiveStorms)
end
RunService.Heartbeat:Connect(function(dt)
local t = tick()
for idx, Storm in ipairs(ActiveStorms) do
if not Storm.Active or not Storm.Model.PrimaryPart then continue end
local rootPos = Storm.Core.Position
if #Storm.Path > 0 and Storm.Waypoint <= #Storm.Path then
local targetPos = Vector3.new(Storm.Path[Storm.Waypoint].Position.X, rootPos.Y, Storm.Path[Storm.Waypoint].Position.Z)
local diff = targetPos - rootPos
if diff.Magnitude < 5 then
Storm.Waypoint += 1
else
Storm.Core.Position = rootPos + (diff.Unit * Settings.WanderSpeed * dt)
end
end
for _, data in ipairs(Storm.Segments) do
local rotAngle = t * data.Speed * Settings.RotationSpeed
local wobbleX = math.sin(t * 2 + (data.Height * 0.05)) * (data.Height * 0.05)
local wobbleZ = math.cos(t * 2 + (data.Height * 0.05)) * (data.Height * 0.05)
data.Part.CFrame = CFrame.new(rootPos + Vector3.new(wobbleX, data.Height, wobbleZ)) * CFrame.Angles(0, rotAngle, 0) * CFrame.Angles(0, 0, math.rad(90))
end
local stats = EF_STATS[Settings.EF_Level]
local searchRadius = stats.Radius * Settings.RadiusMult
if t >= Storm.NextScan then
Storm.NextScan = t + 0.25
local parts = workspace:GetPartBoundsInRadius(rootPos, searchRadius)
local validParts = {}
for _, p in ipairs(parts) do
if p:IsA("BasePart") and not p.Anchored and p.Size.Magnitude < 150 then
if not isDescendantOfPlayerCharacter(p) then
table.insert(validParts, p)
end
end
end
Storm.CachedParts = validParts
end
for _, p in ipairs(Storm.CachedParts) do
if p and p.Parent then
local offset = p.Position - rootPos
local horizontalDist = Vector3.new(offset.X, 0, offset.Z).Magnitude
local suctionForce = math.clamp(1 - (horizontalDist / searchRadius), 0, 1)
local baseStrength = stats.Strength * Settings.PullStrengthMult
local tangent = Vector3.new(-offset.Z, 0, offset.X).Unit
local pull = -offset.Unit * (baseStrength * 0.5)
local lift = Vector3.new(0, (baseStrength * 1.5) * Settings.LiftSpeed, 0)
local spin = tangent * (baseStrength * 2.5) * Settings.RotationSpeed
p.AssemblyLinearVelocity = (spin + lift + pull) * suctionForce
end
end
end
end)



is it normal that an ui is stuck on my screen saying "STORM OS v8.0 - CHANGELOG"