
KeylessUniversal

-- SCRIPT DE TORNADOS COMBINADOS (MENOR NO INÍCIO + MAIOR APÓS 5 MINUTOS)
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local LocalPlayer = Players.LocalPlayer
local Character = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()
local RootPart = Character:WaitForChild("HumanoidRootPart")
local ID_SOM = "rbxassetid://123731555496199"
-- FUNÇÃO GERADORA DE TORNADO
local function criarTornado(config)
local ALCANCE_SUCCAO = config.AlcanceSuccao or 50
local FORCA_PUXAO = config.ForcaPuxao or 10
local VELOCIDADE_TORNADO = config.Velocidade or 8
local ALTURA_NUVENS = config.AlturaNuvens or 350
local DISTANCIA_SPAWN = config.DistanciaSpawn or 80
local LARGURA_BASE = config.LarguraBase or 12
local LARGURA_TOPO = config.LarguraTopo or 200
local QTD_BLOCOS = config.QtdBlocos or 6
-- 1. Base do Tornado
local posicaoInicial = RootPart.CFrame * CFrame.new(0, 0, -DISTANCIA_SPAWN)
local baseTornado = Instance.new("Part")
baseTornado.Name = config.Nome or "BaseTornado"
baseTornado.Size = Vector3.new(20, 1, 20)
baseTornado.CFrame = CFrame.new(posicaoInicial.Position)
baseTornado.Anchored = true
baseTornado.CanCollide = false
baseTornado.Transparency = 1
baseTornado.Parent = workspace
-- 2. Som em Loop
local somTornado = Instance.new("Sound")
somTornado.Name = "SomTornado"
somTornado.SoundId = ID_SOM
somTornado.Volume = config.Volume or 2
somTornado.Looped = true
somTornado.RollOffMaxDistance = config.DistanciaSom or 500
somTornado.RollOffMinDistance = 20
somTornado.Parent = baseTornado
somTornado:Play()
-- 3. Nuvens no Céu
local nuvemSky = Instance.new("Part")
nuvemSky.Size = Vector3.new(1, 1, 1)
nuvemSky.Anchored = true
nuvemSky.CanCollide = false
nuvemSky.Transparency = 1
nuvemSky.CFrame = baseTornado.CFrame * CFrame.new(0, ALTURA_NUVENS, 0)
nuvemSky.Parent = workspace
local attachmentNuvem = Instance.new("Attachment", nuvemSky)
local emissorNuvem = Instance.new("ParticleEmitter", attachmentNuvem)
emissorNuvem.Texture = "rbxasset://textures/particles/smoke_main.dds"
emissorNuvem.Rate = config.TaxaFumaca or 150
emissorNuvem.Lifetime = NumberRange.new(6, 10)
emissorNuvem.Speed = NumberRange.new(15, 30)
emissorNuvem.SpreadAngle = Vector2.new(180, 180)
emissorNuvem.Color = ColorSequence.new(Color3.fromRGB(170, 170, 180))
emissorNuvem.Size = NumberSequence.new({
NumberSequenceKeypoint.new(0, 60),
NumberSequenceKeypoint.new(0.5, 180),
NumberSequenceKeypoint.new(1, 250)
})
emissorNuvem.Transparency = NumberSequence.new({
NumberSequenceKeypoint.new(0, 0.6),
NumberSequenceKeypoint.new(0.5, 0.2),
NumberSequenceKeypoint.new(1, 1)
})
-- 4. Chuva
local emissorChuva = Instance.new("ParticleEmitter", attachmentNuvem)
emissorChuva.Texture = "rbxasset://textures/particles/sparkles_main.dds"
emissorChuva.Rate = 400
emissorChuva.Lifetime = NumberRange.new(3, 5)
emissorChuva.Speed = NumberRange.new(120, 180)
emissorChuva.EmissionDirection = Enum.NormalId.Bottom
emissorChuva.Acceleration = Vector3.new(0, -200, 0)
emissorChuva.Orientation = Enum.ParticleOrientation.VelocityParallel
emissorChuva.SpreadAngle = Vector2.new(45, 45)
emissorChuva.Color = ColorSequence.new(Color3.fromRGB(180, 210, 255))
emissorChuva.Size = NumberSequence.new({
NumberSequenceKeypoint.new(0, 1),
NumberSequenceKeypoint.new(1, 1.5)
})
emissorChuva.Transparency = NumberSequence.new({
NumberSequenceKeypoint.new(0, 0.2),
NumberSequenceKeypoint.new(1, 0.6)
})
-- 5. Corpo do Tornado
local attachmentBase = Instance.new("Attachment", baseTornado)
local fumacaCorpo = Instance.new("ParticleEmitter", attachmentBase)
fumacaCorpo.Texture = "rbxasset://textures/particles/smoke_main.dds"
fumacaCorpo.Rate = config.TaxaFumaca or 220
fumacaCorpo.Lifetime = NumberRange.new(6, 9)
fumacaCorpo.Speed = NumberRange.new(45, 75)
fumacaCorpo.SpreadAngle = Vector2.new(10, 10)
fumacaCorpo.Acceleration = Vector3.new(0, 30, 0)
fumacaCorpo.Color = ColorSequence.new(Color3.fromRGB(180, 180, 190))
fumacaCorpo.Size = NumberSequence.new({
NumberSequenceKeypoint.new(0, LARGURA_BASE),
NumberSequenceKeypoint.new(0.5, LARGURA_TOPO * 0.45),
NumberSequenceKeypoint.new(1, LARGURA_TOPO)
})
fumacaCorpo.RotSpeed = NumberRange.new(300, 600)
-- 6. Blocos Voando
local blocosVoadores = {}
for i = 1, QTD_BLOCOS do
local bloco = Instance.new("Part")
bloco.Size = Vector3.new(4, 4, 4)
bloco.Color = Color3.fromRGB(180, 150, 120)
bloco.Material = Enum.Material.Wood
bloco.Anchored = true
bloco.CanCollide = false
bloco.Parent = workspace
table.insert(blocosVoadores, {
Objeto = bloco,
Altura = math.random(5, 120),
Angulo = math.random(0, 360),
RaioGiro = math.random(15, 45)
})
end
-- 7. Movimentação do Tornado
local function getNovoDestino()
return Vector3.new(
baseTornado.Position.X + math.random(-600, 600),
posicaoInicial.Position.Y,
baseTornado.Position.Z + math.random(-600, 600)
)
end
local destinoAtual = getNovoDestino()
-- 8. Loop Principal (RenderStepped)
local tempoSegurando = 0
local noTornado = false
local cooldownArremesso = 0
local anguloJogador = 0
local conexao = RunService.RenderStepped:Connect(function(dt)
if not baseTornado or not baseTornado.Parent then return end
-- Mover base
local direcao = (destinoAtual - baseTornado.Position)
if direcao.Magnitude < 20 then
destinoAtual = getNovoDestino()
else
local proximaPosicao = baseTornado.Position + (direcao.Unit * VELOCIDADE_TORNADO * dt)
baseTornado.CFrame = CFrame.new(proximaPosicao)
end
nuvemSky.CFrame = baseTornado.CFrame * CFrame.new(0, ALTURA_NUVENS, 0)
-- Animação dos blocos
for _, dados in ipairs(blocosVoadores) do
dados.Angulo = dados.Angulo + (4 * dt)
dados.Altura = dados.Altura + (25 * dt)
if dados.Altura > 200 then dados.Altura = 5 end
local raio = (dados.Altura / 200) * dados.RaioGiro + 10
local x = math.cos(dados.Angulo) * raio
local z = math.sin(dados.Angulo) * raio
dados.Objeto.CFrame = CFrame.new(baseTornado.Position + Vector3.new(x, dados.Altura, z))
end
-- Atração do jogador
if RootPart and Character:FindFirstChild("Humanoid") then
local posCentro = Vector3.new(baseTornado.Position.X, 0, baseTornado.Position.Z)
local posJogador = Vector3.new(RootPart.Position.X, 0, RootPart.Position.Z)
local distancia = (posJogador - posCentro).Magnitude
if cooldownArremesso > 0 then
cooldownArremesso = cooldownArremesso - dt
elseif distancia <= ALCANCE_SUCCAO or noTornado then
noTornado = true
tempoSegurando = tempoSegurando + dt
anguloJogador = anguloJogador + (6 * dt)
if tempoSegurando < 2 then
local raioGiro = (LARGURA_BASE > 20) and 28 or 15
local offsetX = math.cos(anguloJogador) * raioGiro
local offsetZ = math.sin(anguloJogador) * raioGiro
local alvoX = baseTornado.Position.X + offsetX
local alvoZ = baseTornado.Position.Z + offsetZ
RootPart.AssemblyLinearVelocity = Vector3.new(
(alvoX - RootPart.Position.X) * FORCA_PUXAO,
20,
(alvoZ - RootPart.Position.Z) * FORCA_PUXAO
)
else
local direcaoFora = (RootPart.Position - baseTornado.Position).Unit
if direcaoFora.Magnitude == 0 then
direcaoFora = Vector3.new(math.random(-1,1), 0, math.random(-1,1)).Unit
end
local forcaArremesso = (LARGURA_BASE > 20) and 220 or 180
RootPart.AssemblyLinearVelocity = (direcaoFora * forcaArremesso) + Vector3.new(0, 120, 0)
noTornado = false
tempoSegurando = 0
cooldownArremesso = 3
end
else
tempoSegurando = 0
noTornado = false
end
end
end)
end
-- 1. TORNADO MENOR (SPAWNA NA HORA)
print("🌀 Tornado Menor spawnando agora...")
criarTornado({
Nome = "TornadoMenor",
AlcanceSuccao = 50,
ForcaPuxao = 10,
Velocidade = 8,
AlturaNuvens = 350,
DistanciaSpawn = 80,
LarguraBase = 12,
LarguraTopo = 200,
QtdBlocos = 6,
Volume = 2,
DistanciaSom = 500,
TaxaFumaca = 220
})
-- 2. TORNADO MAIOR E GROSSO (SPAWNA A 5 MINUTOS / 300 SEGUNDOS)
task.spawn(function()
task.wait(300) -- Aguarda 5 minutos
print("🌪️ 5 minutos se passaram! Spawnando Tornado Gigante a 300 blocos...")
criarTornado({
Nome = "TornadoMaiorGigante",
AlcanceSuccao = 90,
ForcaPuxao = 20,
Velocidade = 8,
AlturaNuvens = 350,
DistanciaSpawn = 300,
LarguraBase = 35,
LarguraTopo = 280,
QtdBlocos = 8,
Volume = 2.5,
DistanciaSom = 800,
TaxaFumaca = 300
})
end)



everyone wont see itt 😭