Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local AssetService = game:GetService("AssetService")
- local Selection = game:GetService("Selection")
- local ScriptEditorService = game:GetService("ScriptEditorService")
- local ServerStorage = game:GetService("ServerStorage")
- local KeyframeSequenceProvider = game:GetService("KeyframeSequenceProvider")
- local CoreGui = game:GetService("CoreGui")
- local prup = {
- "Size", "CFrame", "Color", "Material", "Transparency", "Reflectance",
- "CanCollide", "CanTouch", "CanQuery", "Anchored", "Massless", "CastShadow",
- "CollisionGroup", "TopSurface", "BottomSurface", "LeftSurface", "RightSurface",
- "Friction", "Elasticity", "CustomPhysicalProperties", "RootPriority"
- }
- local x_prup = {
- Part = {"Shape"},
- MeshPart = {"MeshId", "TextureID", "RenderFidelity", "CollisionFidelity", "DoubleSided"},
- SpecialMesh = {"MeshType", "MeshId", "TextureId", "Scale", "Offset", "VertexColors"},
- Decal = {"Texture", "Transparency", "Color3", "Face", "ZIndex"},
- Texture = {"Texture", "Transparency", "Color3", "Face", "ZIndex", "StudsPerTileU", "StudsPerTileV", "OffsetStudsU", "OffsetStudsV"},
- SurfaceAppearance = {"ColorMap", "NormalMap", "MetalnessMap", "RoughnessMap", "AlphaMode"},
- CharacterMesh = {"BodyPart", "MeshId", "BaseTextureId", "OverlayTextureId"},
- Tool = {"Grip", "GripPos", "GripForward", "GripRight", "GripUp", "CanBeDropped", "ManualActivationOnly", "RequiresHandle", "ToolTip", "Enabled"},
- Accessory = {"AttachmentPoint", "AccessoryType"},
- Accoutrement = {"AttachmentPoint"},
- Shirt = {"ShirtTemplate", "Color3"},
- Pants = {"PantsTemplate", "Color3"},
- ShirtGraphic = {"Graphic", "Color3"},
- Humanoid = {
- "RigType", "HipHeight", "WalkSpeed", "JumpPower", "JumpHeight",
- "MaxHealth", "Health", "AutoRotate", "DisplayDistanceType",
- "HealthDisplayType", "HealthDisplayDistance", "NameDisplayDistance",
- "BreakJointsOnDeath", "RequiresNeck", "AutomaticScalingEnabled", "UseJumpPower"
- },
- Animation = {"AnimationId"},
- Animator = {"EvaluationType"},
- AnimationController = {},
- Bone = {"CFrame", "Transform"},
- BodyColors = {"HeadColor3", "TorsoColor3", "LeftArmColor3", "RightArmColor3", "LeftLegColor3", "RightLegColor3"},
- KeyframeSequence = {"Loop", "Priority"},
- Keyframe = {"Time"},
- Pose = {"CFrame", "EasingDirection", "EasingStyle", "Weight"},
- NumberPose = {"Value", "EasingDirection", "EasingStyle", "Weight"},
- KeyframeMarker = {"Value"},
- ProximityPrompt = {
- "ActionText", "ObjectText", "HoldDuration", "MaxActivationDistance",
- "RequiresLineOfSight", "KeyboardKeyCode", "GamepadKeyCode", "ClickablePrompt",
- "Enabled", "Exclusivity", "UIOffset", "AutoLocalize", "Style"
- },
- ClickDetector = {"MaxActivationDistance", "CursorIcon"},
- Dialog = {"InitialPrompt", "Purpose", "Tone", "GoodbyeDialog", "InUse"},
- DialogChoice = {"UserDialog", "ResponseDialog", "GoodbyeDialog"},
- Script = {"Source", "Enabled", "RunContext"},
- LocalScript = {"Source", "Enabled"},
- ModuleScript = {"Source"},
- Motor6D = {"C0", "C1", "MaxVelocity", "DesiredAngle", "CurrentAngle", "Enabled"},
- Weld = {"C0", "C1", "Enabled"},
- ManualWeld = {"C0", "C1", "Enabled"},
- WeldConstraint = {"Enabled"},
- Snap = {"C0", "C1", "Enabled"},
- Attachment = {"CFrame", "Visible"},
- NoCollisionConstraint = {"Enabled"},
- BallSocketConstraint = {"LimitsEnabled", "UpperAngle", "TwistLimitsEnabled", "TwistLowerAngle", "TwistUpperAngle", "Radius", "Restitution", "Enabled"},
- HingeConstraint = {"LimitsEnabled", "LowerAngle", "UpperAngle", "ActuatorType", "MotorMaxTorque", "AngularVelocity", "ServoTargetAngle", "Radius", "Restitution", "AngularSpeed", "Enabled"},
- PrismaticConstraint = {"LimitsEnabled", "LowerLimit", "UpperLimit", "Restitution", "ActuatorType", "MotorMaxAcceleration", "MotorMaxForce", "Velocity", "ServoMaxForce", "TargetPosition", "Speed", "Size", "Enabled"},
- CylindricalConstraint = {"LimitsEnabled", "LowerLimit", "UpperLimit", "Restitution", "ActuatorType", "MotorMaxAcceleration", "MotorMaxForce", "Velocity", "ServoMaxForce", "TargetPosition", "Speed", "AngularLimitsEnabled", "LowerAngle", "UpperAngle", "AngularRestitution", "AngularActuatorType", "MotorMaxAngularAcceleration", "MotorMaxTorque", "AngularVelocity", "AngularServoMaxTorque", "TargetAngle", "AngularSpeed", "RotationAxisVisible", "Size", "Enabled"},
- RodConstraint = {"Length", "Thickness", "Visible", "Enabled"},
- RopeConstraint = {"Length", "Thickness", "Visible", "Restitution", "Enabled"},
- SpringConstraint = {"Coils", "FreeLength", "Radius", "Stiffness", "Damping", "LimitsEnabled", "MaxLength", "MinLength", "Thickness", "Visible", "Enabled"},
- AlignPosition = {"Mode", "MaxForce", "MaxVelocity", "Responsiveness", "RigidityEnabled", "ApplyAtCenterOfMass", "Position", "ReactionForceEnabled", "Enabled"},
- AlignOrientation = {"Mode", "MaxTorque", "MaxAngularVelocity", "Responsiveness", "RigidityEnabled", "CFrame", "ReactionTorqueEnabled", "PrimaryAxisOnly", "AlignType", "Enabled"},
- LinearVelocity = {"VectorVelocity", "MaxForce", "RelativeTo", "VelocityConstraintMode", "Enabled"},
- AngularVelocity = {"AngularVelocity", "MaxTorque", "RelativeTo", "ReactionTorqueEnabled", "Enabled"},
- VectorForce = {"Force", "RelativeTo", "ApplyAtCenterOfMass", "Enabled"},
- Torque = {"Torque", "RelativeTo", "Enabled"},
- PointLight = {"Color", "Brightness", "Range", "Shadows", "Enabled"},
- SpotLight = {"Color", "Brightness", "Range", "Shadows", "Angle", "Face", "Enabled"},
- SurfaceLight = {"Color", "Brightness", "Range", "Shadows", "Angle", "Face", "Enabled"},
- Sound = {"SoundId", "Volume", "PlaybackSpeed", "Looped", "RollOffMode", "RollOffMinDistance", "RollOffMaxDistance", "Playing"},
- ParticleEmitter = {
- "Texture", "Color", "Transparency", "Size", "Lifetime", "Rate", "Speed", "Rotation",
- "RotSpeed", "Acceleration", "SpreadAngle", "EmissionDirection", "LockedToPart",
- "LightInfluence", "LightEmission", "ZOffset", "Drag", "TimeScale", "VelocityInheritance", "Enabled"
- },
- Beam = {
- "Width0", "Width1", "Color", "Transparency", "Texture", "TextureMode", "TextureLength",
- "TextureSpeed", "Segments", "CurveSize0", "CurveSize1", "FaceCamera", "LightEmission",
- "LightInfluence", "ZOffset", "Enabled"
- },
- Trail = {
- "Color", "Transparency", "Lifetime", "MinLength", "WidthScale", "Texture", "TextureMode",
- "TextureLength", "LightEmission", "LightInfluence", "FaceCamera", "MaxLength", "Enabled"
- },
- Highlight = {"FillColor", "FillTransparency", "OutlineColor", "OutlineTransparency", "DepthMode", "Enabled"},
- Fire = {"Color", "SecondaryColor", "Heat", "Size", "Enabled"},
- Smoke = {"Color", "Opacity", "RiseVelocity", "Size", "Enabled"},
- Sparkles = {"SparkleColor", "Enabled"},
- BillboardGui = {
- "AlwaysOnTop", "ExtentsOffset", "ExtentsOffsetWorldSpace", "LightInfluence",
- "MaxDistance", "Size", "SizeOffset", "StudsOffset", "StudsOffsetWorldSpace",
- "Enabled", "ResetOnSpawn", "ClipsDescendants", "Active", "DistanceLowerLimit", "DistanceUpperLimit"
- },
- SurfaceGui = {
- "Face", "AlwaysOnTop", "LightInfluence", "MaxDistance", "CanvasSize",
- "PixelsPerStud", "SizingMode", "ToolPunchThroughDistance", "Enabled", "ClipsDescendants", "Active"
- },
- ScreenGui = {"Enabled", "ResetOnSpawn", "DisplayOrder", "IgnoreGuiInset"},
- Frame = {"BackgroundColor3", "BackgroundTransparency", "BorderColor3", "BorderSizePixel", "Size", "Position", "AnchorPoint", "Visible", "ZIndex", "Rotation", "ClipsDescendants", "LayoutOrder"},
- TextLabel = {
- "Text", "Font", "FontFace", "TextSize", "TextColor3", "TextStrokeColor3", "TextStrokeTransparency",
- "TextTransparency", "TextScaled", "TextWrapped", "TextXAlignment", "TextYAlignment",
- "RichText", "BackgroundColor3", "BackgroundTransparency", "BorderColor3", "BorderSizePixel",
- "Size", "Position", "AnchorPoint", "Visible", "ZIndex", "Rotation", "LayoutOrder", "MaxVisibleGraphemes"
- },
- TextButton = {
- "Text", "Font", "FontFace", "TextSize", "TextColor3", "TextStrokeColor3", "TextStrokeTransparency",
- "TextTransparency", "TextScaled", "TextWrapped", "TextXAlignment", "TextYAlignment",
- "RichText", "BackgroundColor3", "BackgroundTransparency", "BorderColor3", "BorderSizePixel",
- "Size", "Position", "AnchorPoint", "Visible", "ZIndex", "Rotation", "AutoButtonColor", "Active", "LayoutOrder"
- },
- ImageLabel = {
- "Image", "ImageColor3", "ImageTransparency", "ImageRectOffset", "ImageRectSize",
- "ScaleType", "SliceCenter", "SliceScale", "BackgroundColor3", "BackgroundTransparency",
- "BorderColor3", "BorderSizePixel", "Size", "Position", "AnchorPoint", "Visible", "ZIndex", "Rotation", "LayoutOrder"
- },
- ImageButton = {
- "Image", "ImageColor3", "ImageTransparency", "ImageRectOffset", "ImageRectSize",
- "ScaleType", "SliceCenter", "SliceScale", "BackgroundColor3", "BackgroundTransparency",
- "BorderColor3", "BorderSizePixel", "Size", "Position", "AnchorPoint", "Visible", "ZIndex", "Rotation", "AutoButtonColor", "Active", "LayoutOrder"
- },
- UICorner = {"CornerRadius"},
- UIStroke = {"Color", "Thickness", "Transparency", "ApplyStrokeMode", "LineJoinMode", "Enabled"},
- UIGradient = {"Color", "Transparency", "Offset", "Rotation", "Enabled"},
- UIAspectRatioConstraint = {"AspectRatio", "AspectType", "DominantAxis"},
- UIScale = {"Scale"},
- Model = {"PrimaryPart", "LevelOfDetail", "WorldPivot"},
- IntValue = {"Value"}, NumberValue = {"Value"}, StringValue = {"Value"}, BoolValue = {"Value"},
- Vector3Value = {"Value"}, CFrameValue = {"Value"}, Color3Value = {"Value"}, ObjectValue = {"Value"}
- }
- local ref_prup = {
- PrimaryPart = true, Part0 = true, Part1 = true,
- Attachment0 = true, Attachment1 = true, Adornee = true, Value = true
- }
- local CLASS_CONV = {TouchTransmitter = "ClickDetector", UnionOperation = "Part"}
- local SKIP_CLASSES = {Terrain = true}
- local PART_LIKE = {Part = true, MeshPart = true, TrussPart = true, CornerWedgePart = true, WedgePart = true, CylinderPart = true, UnionOperation = true}
- local function num(v)
- if v ~= v then return "(0/0)" end
- if v == math.huge then return "math.huge" end
- if v == -math.huge then return "-math.huge" end
- return ("%.17g"):format(v)
- end
- local function emitVal(v)
- local t = typeof(v)
- if t == "number" then return num(v) end
- if t == "boolean" then return tostring(v) end
- if t == "string" then return ("%q"):format(v) end
- if t == "EnumItem" then return tostring(v) end
- if t == "BrickColor" then return ('BrickColor.new("%s")'):format(v.Name) end
- if t == "Vector3" then return ("Vector3.new(%s,%s,%s)"):format(num(v.X), num(v.Y), num(v.Z)) end
- if t == "Vector2" then return ("Vector2.new(%s,%s)"):format(num(v.X), num(v.Y)) end
- if t == "Color3" then return ("Color3.new(%s,%s,%s)"):format(num(v.R), num(v.G), num(v.B)) end
- if t == "UDim2" then return ("UDim2.new(%s,%s,%s,%s)"):format(num(v.X.Scale), num(v.X.Offset), num(v.Y.Scale), num(v.Y.Offset)) end
- if t == "UDim" then return ("UDim.new(%s,%s)"):format(num(v.Scale), num(v.Offset)) end
- if t == "CFrame" then
- local x,y,z,r00,r01,r02,r10,r11,r12,r20,r21,r22 = v:GetComponents()
- return ("CFrame.new(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"):format(num(x),num(y),num(z),num(r00),num(r01),num(r02),num(r10),num(r11),num(r12),num(r20),num(r21),num(r22))
- end
- if t == "NumberRange" then return ("NumberRange.new(%s,%s)"):format(num(v.Min), num(v.Max)) end
- if t == "NumberSequence" then
- local p = {}
- for _, k in ipairs(v.Keypoints) do p[#p+1] = ("NumberSequenceKeypoint.new(%s,%s,%s)"):format(num(k.Time), num(k.Value), num(k.Envelope)) end
- return "NumberSequence.new({" .. table.concat(p, ",") .. "})"
- end
- if t == "ColorSequence" then
- local p = {}
- for _, k in ipairs(v.Keypoints) do p[#p+1] = ("ColorSequenceKeypoint.new(%s,Color3.new(%s,%s,%s))"):format(num(k.Time), num(k.Value.R), num(k.Value.G), num(k.Value.B)) end
- return "ColorSequence.new({" .. table.concat(p, ",") .. "})"
- end
- if t == "PhysicalProperties" then return ("PhysicalProperties.new(%s,%s,%s,%s,%s)"):format(num(v.Density), num(v.Friction), num(v.Elasticity), num(v.FrictionWeight), num(v.ElasticityWeight)) end
- if t == "Rect" then return ("Rect.new(%s,%s,%s,%s)"):format(num(v.Min.X), num(v.Min.Y), num(v.Max.X), num(v.Max.Y)) end
- if t == "Font" then return ('Font.new(%q,%s,%s)'):format(v.Family, tostring(v.Weight), tostring(v.Style)) end
- return nil
- end
- local function isValidMeshId(id)
- if type(id) ~= "string" then return false end
- local t = id:match("^%s*(.-)%s*$")
- if t == "" or t == "0" or t == "rbxassetid://0" or t == "rbxassetid://" or t == "rbxasset://" then return false end
- local l = t:lower()
- if l == "none" or l == "null" or l:find("meshpartfallback") then return false end
- return true
- end
- local function readMeshId(o)
- local ok, v = pcall(function() return o.MeshId end)
- if ok and isValidMeshId(v) then return v end
- local ok2, c = pcall(function() return o.MeshContent end)
- if ok2 and c then
- local ok3, uri = pcall(function() return c.Uri end)
- if ok3 and isValidMeshId(uri) then return uri end
- local s = tostring(c)
- if (s:match("^rbxasset") or s:match("^http")) and isValidMeshId(s) then return s end
- end
- return nil
- end
- local function propListFor(c)
- local l, seen = {}, {}
- local function add(k) if not seen[k] then seen[k] = true; l[#l+1] = k end end
- if PART_LIKE[c] or c == "Part" then for _, k in ipairs(prup) do add(k) end end
- if x_prup[c] then for _, k in ipairs(x_prup[c]) do add(k) end end
- for k in pairs(ref_prup) do add(k) end
- return l
- end
- local function captureActiveAnimations(root)
- local active = {}
- local hum = root:FindFirstChildOfClass("Humanoid") or root:FindFirstChildOfClass("AnimationController")
- if hum then
- local animator = hum:FindFirstChildOfClass("Animator")
- if animator then
- local ok, tracks = pcall(function() return animator:GetPlayingAnimationTracks() end)
- if ok and tracks and #tracks > 0 then
- for _, trk in ipairs(tracks) do
- if trk.IsPlaying and trk.Animation then
- table.insert(active, {
- id = trk.Animation.AnimationId,
- name = trk.Animation.Name,
- speed = trk.Speed,
- weight = trk.WeightCurrent,
- timePos = trk.TimePosition,
- looped = trk.Looped,
- priority = trk.Priority.Name
- })
- end
- end
- end
- end
- end
- if #active == 0 then
- for _, d in ipairs(root:GetDescendants()) do
- if d:IsA("Animation") and (d.Name:lower():find("idle") or (d.Parent and d.Parent.Name:lower():find("idle"))) then
- table.insert(active, {
- id = d.AnimationId,
- name = d.Name,
- speed = 1,
- weight = 1,
- timePos = 0,
- looped = true,
- priority = "Idle"
- })
- break
- end
- end
- end
- return active
- end
- local function serializeSelection(sel)
- local set, roots = {}, {}
- for _, o in ipairs(sel) do set[o] = true end
- for _, o in ipairs(sel) do
- local p, isRoot = o.Parent, true
- while p do if set[p] then isRoot = false; break end; p = p.Parent end
- if isRoot then roots[#roots+1] = o end
- end
- if #roots == 0 then return nil end
- local root, records, index = roots[1], {}, {}
- local activeAnims = captureActiveAnimations(root)
- local function walk(o, pIdx)
- local c = CLASS_CONV[o.ClassName] or o.ClassName
- if SKIP_CLASSES[c] then return end
- local isScript = (c == "Script" or c == "LocalScript" or c == "ModuleScript")
- local isMP = (c == "MeshPart") or (pcall(function() return o:IsA("MeshPart") end) and o:IsA("MeshPart"))
- local mId = nil
- if isMP then
- c = "MeshPart"
- mId = readMeshId(o)
- end
- local rec = {c = c, n = o.Name, p = pIdx, props = {}, refs = {}}
- records[#records+1] = rec
- local myIdx = #records
- index[o] = myIdx
- if isMP and mId then rec.mesh = mId end
- for _, k in ipairs(propListFor(c)) do
- local ok, v = pcall(function() return o[k] end)
- if ok and v ~= nil then
- if typeof(v) == "Instance" then
- if ref_prup[k] then rec.refs[k] = v end
- else
- local ev = emitVal(v)
- if ev then rec.props[k] = ev end
- end
- end
- end
- if isScript then
- local okS, src = pcall(function() return o.Source end)
- if okS and src then rec.props["Source"] = ("%q"):format(src) end
- end
- local okA, attrs = pcall(function() return o:GetAttributes() end)
- if okA and type(attrs) == "table" then
- for k, v in pairs(attrs) do
- local ev = emitVal(v)
- if ev then rec.attrs = rec.attrs or {}; rec.attrs[k] = ev end
- end
- end
- if c == "Animation" and o.AnimationId and o.AnimationId ~= "" then
- pcall(function()
- local kfs = KeyframeSequenceProvider:GetKeyframeSequenceAsync(o.AnimationId)
- if kfs and kfs:IsA("KeyframeSequence") then
- walk(kfs, myIdx)
- end
- end)
- end
- for _, child in ipairs(o:GetChildren()) do walk(child, myIdx) end
- end
- walk(root, 0)
- for o, i in pairs(index) do
- for k, target in pairs(records[i].refs) do records[i].refs[k] = index[target] end
- end
- for _, r in ipairs(records) do
- for k in pairs(r.refs) do if type(r.refs[k]) ~= "number" then r.refs[k] = nil end end
- if next(r.refs) == nil then r.refs = nil end
- if next(r.props) == nil then r.props = nil end
- end
- return records, root.Name, #records, activeAnims
- end
- local RUNTIME = [===[
- local AssetService = game:GetService("AssetService")
- local Players = game:GetService("Players")
- local KeyframeSequenceProvider = game:GetService("KeyframeSequenceProvider")
- local function setProp(o, k, v)
- o[k] = v
- end
- local function setRef(o, k, target)
- o[k] = target
- end
- local mCache = {}
- local function create(r)
- if r.c == "MeshPart" then
- if r.mesh then
- local t = mCache[r.mesh]
- if t == nil then
- local ok, res = pcall(function()
- return AssetService:CreateMeshPartAsync(Content.fromUri(r.mesh), {
- CollisionFidelity = (r.props and r.props.CollisionFidelity) or Enum.CollisionFidelity.Box
- })
- end)
- t = (ok and res) or false
- mCache[r.mesh] = t
- end
- if t then return t:Clone() end
- end
- local part = Instance.new("Part")
- if r.mesh then
- local sm = Instance.new("SpecialMesh")
- sm.MeshType = Enum.MeshType.FileMesh
- sm.MeshId = r.mesh
- if r.props and r.props.TextureID then sm.TextureId = r.props.TextureID end
- sm.Parent = part
- end
- return part
- end
- return Instance.new(r.c)
- end
- local total = #DATA
- local insts = table.create(total)
- for i = 1, total do
- local r = DATA[i]
- local o = create(r)
- if o then o.Name = r.n end
- insts[i] = o
- if i % 250 == 0 then task.wait() end
- end
- for i = 1, total do
- local o = insts[i]
- local r = DATA[i]
- if o then
- if r.props then
- if r.c == "Humanoid" and r.props.MaxHealth then
- pcall(setProp, o, "MaxHealth", r.props.MaxHealth)
- end
- for k, v in pairs(r.props) do
- if not (r.c == "MeshPart" and (k == "CollisionFidelity" or k == "MeshId")) then
- pcall(setProp, o, k, v)
- end
- end
- end
- if r.attrs then
- for k, v in pairs(r.attrs) do pcall(o.SetAttribute, o, k, v) end
- end
- end
- if i % 250 == 0 then task.wait() end
- end
- for i = 1, total do
- local o = insts[i]
- local r = DATA[i]
- if o and r.refs then
- for k, idx in pairs(r.refs) do
- local target = insts[idx]
- if target then pcall(setRef, o, k, target) end
- end
- end
- if i % 250 == 0 then task.wait() end
- end
- for i = 1, total do
- local o = insts[i]
- local r = DATA[i]
- if o and r.p ~= 0 and insts[r.p] then
- o.Parent = insts[r.p]
- end
- end
- local root = insts[1]
- if not root then return end
- for i = 1, total do
- local o = insts[i]
- if o and o:IsA("Animation") then
- local kfs = o:FindFirstChildOfClass("KeyframeSequence")
- if kfs then
- local ok, newId = pcall(function()
- return KeyframeSequenceProvider:RegisterKeyframeSequence(kfs)
- end)
- if ok and newId then o.AnimationId = newId end
- end
- end
- end
- local function getBaseCF()
- local pl = Players.LocalPlayer or Players:FindFirstChildOfClass("Player")
- local c = pl and (pl.Character or pl.CharacterAdded:Wait())
- local hrp = c and c:WaitForChild("HumanoidRootPart", 5)
- if hrp then return hrp.CFrame end
- local sp = workspace:FindFirstChildOfClass("SpawnLocation", true)
- return sp and (sp.CFrame * CFrame.new(0, 4, 0)) or CFrame.new(0, 6, 0)
- end
- if CONFIG.REPLACE then
- for _, e in ipairs(workspace:GetChildren()) do
- if e.Name == CONFIG.NAME then e:Destroy() end
- end
- end
- if root:IsA("Model") then
- if not root.PrimaryPart then
- root.PrimaryPart = root:FindFirstChild("HumanoidRootPart") or root:FindFirstChildWhichIsA("BasePart")
- end
- pcall(function() root:PivotTo(getBaseCF() * CONFIG.OFFSET) end)
- elseif root:IsA("BasePart") then
- root.CFrame = getBaseCF() * CONFIG.OFFSET
- end
- if CONFIG.ANCHOR_MODE == "RootOnly" then
- local hrp = root:FindFirstChild("HumanoidRootPart")
- if hrp then
- hrp.Anchored = true
- for _, d in ipairs(root:GetDescendants()) do
- if d:IsA("BasePart") and d ~= hrp then d.Anchored = false end
- end
- else
- for _, d in ipairs(root:GetDescendants()) do if d:IsA("BasePart") then d.Anchored = true end end
- end
- elseif CONFIG.ANCHOR_MODE == "All" then
- for _, d in ipairs(root:GetDescendants()) do if d:IsA("BasePart") then d.Anchored = true end end
- if root:IsA("BasePart") then root.Anchored = true end
- end
- root.Parent = workspace
- if CONFIG.PLAY_ANIMATIONS and #ACTIVE_ANIMS > 0 then
- local hum = root:FindFirstChildOfClass("Humanoid") or root:FindFirstChildOfClass("AnimationController")
- if hum then
- local animator = hum:FindFirstChildOfClass("Animator") or Instance.new("Animator", hum)
- for _, animData in ipairs(ACTIVE_ANIMS) do
- local targetAnim = nil
- for _, d in ipairs(root:GetDescendants()) do
- if d:IsA("Animation") and (d.AnimationId == animData.id or d.Name == animData.name) then
- targetAnim = d
- break
- end
- end
- if not targetAnim and animData.id and animData.id ~= "" then
- targetAnim = Instance.new("Animation")
- targetAnim.AnimationId = animData.id
- targetAnim.Name = animData.name
- targetAnim.Parent = hum
- end
- if targetAnim then
- task.spawn(function()
- local ok, track = pcall(function() return animator:LoadAnimation(targetAnim) end)
- if ok and track then
- pcall(function()
- track.Priority = Enum.AnimationPriority[animData.priority] or Enum.AnimationPriority.Idle
- track.Looped = (animData.looped ~= nil) and animData.looped or true
- track:Play(0.1, animData.weight or 1, animData.speed or 1)
- if animData.timePos and animData.timePos > 0 then
- track.TimePosition = animData.timePos
- end
- end)
- end
- end)
- end
- end
- end
- end
- ]===]
- local function generateCode(name, records, anchorMode, playAnims, activeAnims)
- local animLines = {}
- for _, a in ipairs(activeAnims) do
- animLines[#animLines + 1] = ('\t{ id = %q, name = %q, speed = %s, weight = %s, timePos = %s, looped = %s, priority = %q },'):format(
- a.id, a.name, num(a.speed), num(a.weight), num(a.timePos), tostring(a.looped), a.priority
- )
- end
- local lines = {
- "local CONFIG = {",
- ('\tNAME = %q,'):format(name),
- "\tOFFSET = CFrame.new(0, 0, -6),",
- ('\tANCHOR_MODE = %q,'):format(anchorMode),
- ('\tPLAY_ANIMATIONS = %s,'):format(tostring(playAnims)),
- "\tREPLACE = true,",
- "}",
- "",
- "local ACTIVE_ANIMS = {",
- table.concat(animLines, "\n"),
- "}",
- "",
- "local DATA = {"
- }
- for _, r in ipairs(records) do
- local p = {('c=%q'):format(r.c), ('n=%q'):format(r.n), ('p=%d'):format(r.p)}
- if r.mesh then p[#p+1] = ('mesh=%q'):format(r.mesh) end
- if r.props then
- local pl = {}
- for k, v in pairs(r.props) do pl[#pl+1] = ("%s=%s"):format(k, v) end
- table.sort(pl)
- p[#p+1] = "props={" .. table.concat(pl, ",") .. "}"
- end
- if r.refs then
- local rl = {}
- for k, idx in pairs(r.refs) do rl[#rl+1] = ("%s=%d"):format(k, idx) end
- table.sort(rl)
- p[#p+1] = "refs={" .. table.concat(rl, ",") .. "}"
- end
- if r.attrs then
- local al = {}
- for k, v in pairs(r.attrs) do al[#al+1] = ("[%q]=%s"):format(k, v) end
- table.sort(al)
- p[#p+1] = "attrs={" .. table.concat(al, ",") .. "}"
- end
- lines[#lines+1] = "\t{ " .. table.concat(p, ", ") .. " },"
- end
- lines[#lines+1] = "}\n"
- return table.concat(lines, "\n") .. RUNTIME
- end
- local function el(class, props, parent)
- local o = Instance.new(class)
- for k, v in pairs(props) do o[k] = v end
- if parent then o.Parent = parent end
- return o
- end
- local function buildUI(parent)
- local pnl = el("Frame", {
- Name = "ModelSaverPanel", Size = UDim2.fromOffset(280, 240), Position = UDim2.new(0.5, -140, 0.5, -120),
- BackgroundColor3 = Color3.fromRGB(18, 18, 18), BorderSizePixel = 0, Active = true
- }, parent)
- el("UICorner", {CornerRadius = UDim.new(0, 4)}, pnl)
- el("UIStroke", {Color = Color3.fromRGB(60, 60, 60), Thickness = 1}, pnl)
- local bar = el("Frame", {
- Name = "TopBar", Size = UDim2.new(1, 0, 0, 26), BackgroundColor3 = Color3.fromRGB(28, 28, 28), BorderSizePixel = 0
- }, pnl)
- el("UICorner", {CornerRadius = UDim.new(0, 4)}, bar)
- el("TextLabel", {
- Size = UDim2.new(1, -30, 1, 0), Position = UDim2.fromOffset(8, 0), BackgroundTransparency = 1,
- Font = Enum.Font.RobotoMono, TextSize = 11, TextColor3 = Color3.fromRGB(240, 240, 240),
- TextXAlignment = Enum.TextXAlignment.Left, Text = "MODEL & NPC SAVER"
- }, bar)
- local cls = el("TextButton", {
- Size = UDim2.fromOffset(20, 20), Position = UDim2.new(1, -23, 0, 3), BackgroundColor3 = Color3.fromRGB(45, 45, 45),
- Text = "×", Font = Enum.Font.GothamBold, TextSize = 12, TextColor3 = Color3.fromRGB(255, 255, 255), BorderSizePixel = 0
- }, bar)
- el("UICorner", {CornerRadius = UDim.new(0, 3)}, cls)
- cls.MouseButton1Click:Connect(function() pnl.Parent:Destroy() end)
- local drag, dStart, sPos
- bar.InputBegan:Connect(function(inp)
- if inp.UserInputType == Enum.UserInputType.MouseButton1 or inp.UserInputType == Enum.UserInputType.Touch then
- drag = true; dStart = inp.Position; sPos = pnl.Position
- inp.Changed:Connect(function() if inp.UserInputState == Enum.UserInputState.End then drag = false end end)
- end
- end)
- bar.InputChanged:Connect(function(inp)
- if (inp.UserInputType == Enum.UserInputType.MouseMovement or inp.UserInputType == Enum.UserInputType.Touch) and drag then
- local delta = inp.Position - dStart
- pnl.Position = UDim2.new(sPos.X.Scale, sPos.X.Offset + delta.X, sPos.Y.Scale, sPos.Y.Offset + delta.Y)
- end
- end)
- local selLbl = el("TextLabel", {
- Size = UDim2.new(1, -16, 0, 18), Position = UDim2.fromOffset(8, 32), BackgroundColor3 = Color3.fromRGB(24, 24, 24),
- Font = Enum.Font.RobotoMono, TextSize = 10, TextColor3 = Color3.fromRGB(180, 180, 180),
- TextXAlignment = Enum.TextXAlignment.Left, Text = " SEL: NONE"
- }, pnl)
- el("UICorner", {CornerRadius = UDim.new(0, 3)}, selLbl)
- local nameInp = el("TextBox", {
- Size = UDim2.new(1, -16, 0, 22), Position = UDim2.fromOffset(8, 54), BackgroundColor3 = Color3.fromRGB(24, 24, 24),
- Font = Enum.Font.RobotoMono, TextSize = 11, TextColor3 = Color3.fromRGB(255, 255, 255),
- PlaceholderColor3 = Color3.fromRGB(110, 110, 110), PlaceholderText = "MODEL NAME", Text = "", ClearTextOnFocus = false
- }, pnl)
- el("UICorner", {CornerRadius = UDim.new(0, 3)}, nameInp)
- local anchorMode = "RootOnly"
- local anchorBtn = el("TextButton", {
- Size = UDim2.new(1, -16, 0, 20), Position = UDim2.fromOffset(8, 80), BackgroundColor3 = Color3.fromRGB(30, 30, 30),
- Font = Enum.Font.RobotoMono, TextSize = 10, TextColor3 = Color3.fromRGB(200, 200, 200),
- Text = " ANCHOR: ROOT ONLY (NPC SAFE)"
- }, pnl)
- el("UICorner", {CornerRadius = UDim.new(0, 3)}, anchorBtn)
- anchorBtn.MouseButton1Click:Connect(function()
- if anchorMode == "RootOnly" then
- anchorMode = "All"
- anchorBtn.Text = " ANCHOR: ALL (MAP/PROP)"
- elseif anchorMode == "All" then
- anchorMode = "None"
- anchorBtn.Text = " ANCHOR: NONE (ORIGINAL)"
- else
- anchorMode = "RootOnly"
- anchorBtn.Text = " ANCHOR: ROOT ONLY (NPC SAFE)"
- end
- end)
- local playAnims = true
- local animBtn = el("TextButton", {
- Size = UDim2.new(1, -16, 0, 20), Position = UDim2.fromOffset(8, 104), BackgroundColor3 = Color3.fromRGB(30, 30, 30),
- Font = Enum.Font.RobotoMono, TextSize = 10, TextColor3 = Color3.fromRGB(120, 255, 120),
- Text = " PLAY ACTIVE ANIM: ON"
- }, pnl)
- el("UICorner", {CornerRadius = UDim.new(0, 3)}, animBtn)
- animBtn.MouseButton1Click:Connect(function()
- playAnims = not playAnims
- animBtn.Text = " PLAY ACTIVE ANIM: " .. (playAnims and "ON" or "OFF")
- animBtn.TextColor3 = playAnims and Color3.fromRGB(120, 255, 120) or Color3.fromRGB(255, 120, 120)
- end)
- local expBtn = el("TextButton", {
- Size = UDim2.new(1, -16, 0, 26), Position = UDim2.fromOffset(8, 130), BackgroundColor3 = Color3.fromRGB(240, 240, 240),
- Font = Enum.Font.GothamBold, TextSize = 11, TextColor3 = Color3.fromRGB(0, 0, 0), Text = "SAVE MODEL"
- }, pnl)
- el("UICorner", {CornerRadius = UDim.new(0, 3)}, expBtn)
- local statLbl = el("TextLabel", {
- Size = UDim2.new(1, -16, 0, 68), Position = UDim2.fromOffset(8, 162), BackgroundColor3 = Color3.fromRGB(24, 24, 24),
- Font = Enum.Font.RobotoMono, TextSize = 9, TextColor3 = Color3.fromRGB(150, 150, 150),
- TextXAlignment = Enum.TextXAlignment.Left, TextYAlignment = Enum.TextYAlignment.Top,
- Text = " READY"
- }, pnl)
- el("UICorner", {CornerRadius = UDim.new(0, 3)}, statLbl)
- local lastSelName = ""
- local function updateSel()
- local sel = Selection:Get()
- if #sel == 0 then
- selLbl.Text = " SEL: NONE"
- else
- local f = sel[1]
- selLbl.Text = (" SEL: %s [%s]"):format(f.Name, f.ClassName)
- if nameInp.Text == "" or nameInp.Text == lastSelName then
- lastSelName = f.Name
- nameInp.Text = f.Name
- end
- end
- end
- Selection.SelectionChanged:Connect(updateSel)
- updateSel()
- expBtn.MouseButton1Click:Connect(function()
- statLbl.Text = " PROCESSING..."
- task.wait()
- local sel = Selection:Get()
- local recs, rootName, count, activeAnims = serializeSelection(sel)
- if not recs or count == 0 then statLbl.Text = " ERR: NO VALID SELECTION"; return end
- local expName = nameInp.Text ~= "" and nameInp.Text or rootName
- expName = expName:gsub('[^%w%-_]', '')
- local code = generateCode(expName, recs, anchorMode, playAnims, activeAnims)
- local ms = Instance.new("ModuleScript")
- ms.Name = "Saved_" .. expName
- ms.Parent = ServerStorage
- local updated = false
- pcall(function()
- ScriptEditorService:UpdateSourceAsync(ms, function()
- return code
- end)
- updated = true
- end)
- if not updated then
- pcall(function() ms.Source = code end)
- end
- local opened = false
- pcall(function()
- ScriptEditorService:OpenScriptDocumentAsync(ms)
- opened = true
- end)
- statLbl.Text = (" OK: %s\n OBJECTS: %d\n ACTIVE ANIMS: %d\n DEST: %s"):format(
- expName, count, #activeAnims, opened and "SCRIPT EDITOR" or "SERVERSTORAGE"
- )
- end)
- return pnl
- end
- if plugin then
- local bar = plugin:CreateToolbar("Model Saver")
- local btn = bar:CreateButton("Save", "Save Model", "")
- local gui = Instance.new("ScreenGui")
- gui.Name = "ModelSaverGui"
- gui.Parent = CoreGui
- gui.Enabled = false
- buildUI(gui)
- btn.Click:Connect(function() gui.Enabled = not gui.Enabled end)
- else
- local gui = Instance.new("ScreenGui", CoreGui)
- gui.Name = "ModelSaverGui"
- buildUI(gui)
- end
Advertisement
Add Comment
Please, Sign In to add comment