Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --Scatter.lua
- --Written by cxcharlie
- --Continue scrolling, I'll explain as you scroll down
- math.randomseed(tick())
- local ReplicatedStorage = game:GetService("ReplicatedStorage")
- local NevermoreEngine = require(ReplicatedStorage:WaitForChild("NevermoreEngine"))
- local LoadCustomLibrary = NevermoreEngine.LoadLibrary
- local qSystems = LoadCustomLibrary("qSystems")
- local Easing = LoadCustomLibrary("Easing")
- function QuaternionFromCFrame(cf)
- local mx, my, mz,
- m00, m01, m02,
- m10, m11, m12,
- m20, m21, m22 = cf:components()
- local trace = m00 + m11 + m22
- if trace > 0 then
- local s = math.sqrt(1 + trace)
- local recip = 0.5/s
- return (m21-m12)*recip, (m02-m20)*recip, (m10-m01)*recip, s*0.5
- else
- local i = 0
- if m11 > m00 then i = 1 end
- if m22 > (i == 0 and m00 or m11) then i = 2 end
- if i == 0 then
- local s = math.sqrt(m00-m11-m22+1)
- local recip = 0.5/s
- return 0.5*s, (m10+m01)*recip, (m20+m02)*recip, (m21-m12)*recip
- elseif i == 1 then
- local s = math.sqrt(m11-m22-m00+1)
- local recip = 0.5/s
- return (m01+m10)*recip, 0.5*s, (m21+m12)*recip, (m02-m20)*recip
- elseif i == 2 then
- local s = math.sqrt(m22-m00-m11+1)
- local recip = 0.5/s
- return (m02+m20)*recip, (m12+m21)*recip, 0.5*s, (m10-m01)*recip
- end
- end
- end
- function QuaternionToCFrame(px, py, pz, x, y, z, w)
- local xs, ys, zs = x + x, y + y, z + z
- local wx, wy, wz = w*xs, w*ys, w*zs
- local xx = x*xs
- local xy = x*ys
- local xz = x*zs
- local yy = y*ys
- local yz = y*zs
- local zz = z*zs
- return CFrame.new(px, py, pz, 1-(yy+zz), xy - wz, xz + wy, xy + wz, 1-(xx+zz), yz - wx, xz - wy, yz + wx, 1-(xx+yy))
- end
- function QuaternionSlerp(a, b, t)
- local cosTheta = a[1]*b[1] + a[2]*b[2] + a[3]*b[3] + a[4]*b[4]
- local startInterp, finishInterp;
- if cosTheta >= 0.0001 then
- if (1 - cosTheta) > 0.0001 then
- local theta = math.acos(cosTheta)
- local invSinTheta = 1/math.sin(theta)
- startInterp = math.sin((1-t)*theta)*invSinTheta
- finishInterp = math.sin(t*theta)*invSinTheta
- else
- startInterp = 1-t
- finishInterp = t
- end
- else
- if (1+cosTheta) > 0.0001 then
- local theta = math.acos(-cosTheta)
- local invSinTheta = 1/math.sin(theta)
- startInterp = math.sin((t-1)*theta)*invSinTheta
- finishInterp = math.sin(t*theta)*invSinTheta
- else
- startInterp = t-1
- finishInterp = t
- end
- end
- return a[1] * startInterp + b[1] * finishInterp,
- a[2] * startInterp + b[2] * finishInterp,
- a[3] * startInterp + b[3] * finishInterp,
- a[4] * startInterp + b[4] * finishInterp
- end
- function SlerpCFrame(a, b, scale)
- local qa = {QuaternionFromCFrame(a)}
- local qb = {QuaternionFromCFrame(b)}
- local ax, ay, az = a.x, a.y, a.z
- local bx, by, bz = b.x, b.y, b.z
- local _scale = 1 - scale;
- return QuaternionToCFrame(_scale * ax + scale*bx, _scale*ay + scale*by, _scale*az + scale*bz, QuaternionSlerp(qa, qb, scale))
- end
- local function GetParts(a)
- local f = {}
- for _,v in pairs(a:GetChildren()) do
- if ypcall(function()local d=v:IsA('BasePart')end) then
- if v:IsA('BasePart') then
- f[#f+1] = v
- end
- if ypcall(function()local d=v:GetChildren()end) then
- if #v:GetChildren() >= 1 then
- table.foreach(GetParts(v),function(ind,val) f[#f+1] = val;end)
- end
- end
- end
- end
- return f
- end
- qSystems:Import(getfenv(0));
- local Main = {}
- local MR = math.random
- --Gets the normal CFrame relative to the model's orignial center CFrame
- --model:The model
- --Returns: (A table of {part,part CFrame offset} or "CF_DATA" Accoutrement (not of much use)), The center of the model
- function GetCFrameHierarchy(model)
- if not type(model) == 'userdata' then return end
- if not model.ClassName == 'Model' then return end
- if model:FindFirstChild('CF_DATA') then model.CF_DATA:remove() end
- local OriginOffsets = {}
- local modelCenter = model:GetModelCFrame()
- local Parts = GetParts(model)
- if #Parts < 500 then --Just in case because table may "lose" its values
- for _,v in pairs(Parts) do table.insert(OriginOffsets,{v,v.CFrame:toObjectSpace(modelCenter)}) end
- return OriginOffsets,modelCenter
- else
- local cf = Instance.new('Accoutrement',model)
- cf.Name = 'CF_DATA'
- for _,v in pairs(Parts) do
- if v.ClassName == 'Part' then
- if v:FindFirstChild('DATA') then v.DATA:remove() end
- local off = v.CFrame:toObjectSpace(modelCenter)
- local nv = Instance.new('CFrameValue',v)
- nv.Name = 'DATA'
- nv.Value = off
- end end
- return cf,modelCenter
- end
- end
- Main.GetCFrameHierarchy = GetCFrameHierarchy
- --Spreads the models parts randomly
- --model: The model -_-
- --radius: The max distance each part can be offset
- --intensity: The max degree/radian the parts can be rotated about
- --callback: The function that is applied to each found part
- function Scatter(model,radius,intensity,callback)
- math.randomseed(tick())
- if not type(model) == 'userdata' then return end
- if not model.ClassName == 'Model' then return end
- --if model:FindFirstChild('CF_DATA') then model.CF_DATA:remove() end
- local Parts = GetParts(model)
- for _,v in pairs(Parts) do
- v.CFrame = (v.CFrame * CFrame.Angles(MR(-intensity,intensity),MR(-intensity,intensity),MR(-intensity,intensity)) * CFrame.new(MR(-radius,radius),MR(-radius,radius),MR(-radius,radius)))
- end
- callback(Parts)
- end
- Main.Scatterz = Scatter
- --When a model is "scattered", this will rearange it back to normal
- --model: The model -___-
- --time: The approximate time it should take (not exact)
- --c: The callback which takes the arguments of the part being tweened and the progress (alpha)
- --See example below
- function TweenBack(model,time,c,hierarchy,center)
- local found = {}
- if model:FindFirstChild('CF_DATA') ~= nil and type(hierarchy) == 'userdata' then
- for _,v in pairs(model:GetChildren()) do
- if v.ClassName == 'Part' then
- if v:FindFirstChild('DATA') ~= nil then
- table.insert(found,{v,v.DATA.Value})
- end end end
- for _,v in pairs(found) do
- local origin = v[1].CFrame
- local goal = (center:toWorldSpace(v[2]:inverse()))
- coroutine.wrap(function()
- for i = 1,(time*29.99) do
- Game:GetService('RunService').RenderStepped:wait()
- v[1].CFrame = SlerpCFrame(origin, goal, i/(time*29.99))
- if c then c(v[1],i/(time*29.99)) end
- end
- ypcall(function()model.CF_DATA:remove()end)
- ypcall(function()for _,v in pairs(GetParts(model)) do if v:FindFirstChild('DATA') then v.DATA:remove() end end end)
- end)()
- end
- elseif model:FindFirstChild('CF_DATA') == nil and type(hierarchy) == 'table' then
- for _,v in pairs(hierarchy) do
- coroutine.wrap(function()
- local start = tick()
- local origin = v[1].CFrame
- local goal = (center:toWorldSpace(v[2]:inverse()))
- for i = 1,(time*29.99) do
- Game:GetService('RunService').RenderStepped:wait()
- v[1].CFrame = SlerpCFrame(origin, goal, i/(time*29.99))
- if c then c(v[1],i/(time*29.99)) end
- end
- end)()
- end
- end
- end
- Main.TweenBack = TweenBack
- function ManualTweenBack(model,hierarchy,center,callback)
- local found = {}
- if model:FindFirstChild('CF_DATA') ~= nil and type(hierarchy) == 'userdata' then
- for _,v in pairs(model:GetChildren()) do
- if v.ClassName == 'Part' then
- if v:FindFirstChild('DATA') ~= nil then
- table.insert(found,{v,v.DATA.Value})
- end end end
- return function(alpha)
- for _,v in pairs(found) do
- local origin = v[1].CFrame
- local goal = (center:toWorldSpace(v[2]:inverse()))
- v[1].CFrame = SlerpCFrame(origin, goal, alpha)
- if callback then ypcall(function()callback(v[1],alpha)end) end
- end
- if alpha == 1 then
- ypcall(function()model.CF_DATA:remove()end)
- ypcall(function()for _,v in pairs(GetParts(model)) do if v:FindFirstChild('DATA') then v.DATA:remove() end end end)
- end
- end
- elseif model:FindFirstChild('CF_DATA') == nil and type(hierarchy) == 'table' then
- return function(alpha)
- for _,v in pairs(hierarchy) do
- local origin = v[1].CFrame
- local goal = (center:toWorldSpace(v[2]:inverse()))
- v[1].CFrame = SlerpCFrame(origin, goal, alpha)
- if callback then ypcall(function()callback(v[1],alpha)end) end
- if alpha == 1 then
- ypcall(function()for _,v in pairs(GetParts(model)) do if v:FindFirstChild('DATA') then v.DATA:remove() end end end)
- end
- end
- end
- end
- end
- Main.ManualTweenBack = ManualTweenBack
- function TweenBackEase(model,time,hierarchy,center,easing,callback,finished)
- local start = tick()
- coroutine.wrap(function()
- local step = ManualTweenBack(model,hierarchy,center,callback)
- local now=0
- local alpha=0
- while game:GetService('RunService').RenderStepped:wait() and alpha<1 do
- now = tick()-start
- alpha = easing(now,0,1,time)
- step(alpha)
- end
- if finished then ypcall(function()finished()end) end
- end)()
- end
- Main.TweenBackEase = TweenBackEase
- local RemoteEvent --= NevermoreEngine.GetEventStreamObject("Tween")
- function FakeModelTweenEase(model,radius,intensity,time,easing,callback1,callback2,f,b)
- if not b then
- pcall(function()RemoteEvent:FireAllClients(model,radius,intensity,time,easing,callback1,callback2,f,true)end)
- end
- if not callback1 then callback1 = function()end end
- if not callback2 then callback2 = function()end end
- if not easing then easing = Easing.inQuad end
- local Fake = model:Clone()
- local h,c = GetCFrameHierarchy(Fake)
- Scatter(Fake,radius,intensity,callback1)
- Fake.Parent = game:GetService('Workspace').CurrentCamera
- if not b then
- TweenBackEase(Fake,time,h,c,easing,callback2,function()
- model:MakeJoints()
- model.Parent=game:GetService('Workspace')Fake:remove()
- coroutine.wrap(f)()
- ypcall(function()model:MakeJoints()end)
- end)
- else
- TweenBackEase(Fake,time,h,c,easing,callback2,function()Fake:remove()end)
- end
- end
- --RemoteEvent.OnClientEvent:connect(FakeModelTweenEase)
- Main.FakeModelTweenEase = FakeModelTweenEase
- return Main
- --[[
- --Press play to see what happens
- local norm,OriginalCenter = GetCFrameHierarchy(script.Parent.Noobie)
- wait(5)
- --You can do what ever and break up your model and stuff
- Scatter(script.Parent.Noobie,4,math.rad(30),function(tab)
- for _,v in pairs(tab) do v.Transparency = 1 end --makes part invisible
- end)
- wait(3)
- --Now the model is back
- TweenBack(script.Parent.Noobie,5,function(part,progress) --this funciton iterates through each part
- part.Transparency = 1 - progress --makes fade in effect
- end,norm,OriginalCenter)
- ]]--
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement