Model Saver
Key RequiredUniversal

Model Saver

Universal Scriptwumpawumpa 394 views 387 executesUpdated Oct 1, 2026
Unrated
00
Lua Script•774 lines (30761 chars)
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

Features & Information

so basically u can go into studio paste it execute click a model in the explorer and press convert button or wtvr its called then it will pop up a new script and that script converted the model into a localscript u can execute and spawn back into normal roblox client sidedly

Community Comments (1)

wumpawumpaOct 7, 2026

u can use this for importing objects into ur scripts for tuff clientsidededness

More Scripts for Universal Scripts