Dark_Agent

FE Nano Mech Reanim script 01

Jan 3rd, 2026 (edited)
322
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 73.38 KB | Gaming | 0 0
  1. if not game:IsLoaded() then game.Loaded:Wait() end
  2.  
  3. local function missing(t, f, fallback)
  4.     if type(f) == t then return f end
  5.     return fallback
  6. end
  7.  
  8. getgenv = missing("function", getgenv, function() return _G end)
  9. cloneref = missing("function", cloneref, function(...) return ... end)
  10. newcclosure = missing("function", newcclosure, function(f) return f end)
  11. setscriptable = missing("function", setscriptable, nil)
  12. sethiddenproperty = missing("function", sethiddenproperty or set_hidden_property or set_hidden_prop, nil)
  13. getnilinstances = missing("function", getnilinstances, function() return {} end)
  14. setclipboard = missing("function", setclipboard or toclipboard or set_clipboard, nil)
  15.  
  16. if getgenv().NanoRunning then
  17.     if getgenv().NanoAPI and getgenv().NanoAPI.Stop then
  18.         getgenv().NanoAPI.Stop()
  19.     end
  20.     task.wait(0.5)
  21. end
  22. getgenv().NanoRunning = true
  23.  
  24. local sethidden = newcclosure(function(instance, property, value)
  25.     local success = pcall(function()
  26.         if sethiddenproperty then
  27.             sethiddenproperty(instance, property, value)
  28.         elseif setscriptable then
  29.             setscriptable(instance, property, true)
  30.             instance[property] = value
  31.             task.wait()
  32.             setscriptable(instance, property, false)
  33.         else
  34.             instance[property] = value
  35.         end
  36.     end)
  37.     return success
  38. end)
  39.  
  40. local Services = setmetatable({}, {
  41.     __index = function(self, name)
  42.         local success, cache = pcall(function()
  43.             return cloneref(game:GetService(name))
  44.         end)
  45.         if success then
  46.             rawset(self, name, cache)
  47.             return cache
  48.         end
  49.         return nil
  50.     end
  51. })
  52.  
  53. local Players = Services.Players
  54. local RunService = Services.RunService
  55. local Workspace = Services.Workspace
  56. local StarterGui = Services.StarterGui
  57. local UserInputService = Services.UserInputService
  58. local PhysicsService = Services.PhysicsService
  59. local CoreGui = Services.CoreGui
  60. local LocalPlayer = Players.LocalPlayer
  61.  
  62. local STARTING = false
  63. local STARTED = false
  64.  
  65. local NANO_GROUP = "NanoParts"
  66. local CHAR_GROUP = "NanoChar"
  67.  
  68. pcall(function()
  69.     PhysicsService:RegisterCollisionGroup(NANO_GROUP)
  70.     PhysicsService:RegisterCollisionGroup(CHAR_GROUP)
  71. end)
  72. pcall(function()
  73.     PhysicsService:CollisionGroupSetCollidable(NANO_GROUP, NANO_GROUP, false)
  74.     PhysicsService:CollisionGroupSetCollidable(NANO_GROUP, CHAR_GROUP, false)
  75.     PhysicsService:CollisionGroupSetCollidable(NANO_GROUP, "Default", false)
  76.     PhysicsService:CollisionGroupSetCollidable(CHAR_GROUP, "Default", true)
  77.     PhysicsService:CollisionGroupSetCollidable(CHAR_GROUP, CHAR_GROUP, false)
  78. end)
  79.  
  80. local ROTATIONS = {
  81.     {cf = CFrame.Angles(0, 0, 0), order = {1, 2, 3}},
  82.     {cf = CFrame.Angles(math.rad(90), 0, 0), order = {1, 3, 2}},
  83.     {cf = CFrame.Angles(0, math.rad(90), 0), order = {3, 2, 1}},
  84.     {cf = CFrame.Angles(0, 0, math.rad(90)), order = {2, 1, 3}},
  85.     {cf = CFrame.Angles(math.rad(90), math.rad(90), 0), order = {3, 1, 2}},
  86.     {cf = CFrame.Angles(math.rad(90), 0, math.rad(90)), order = {2, 3, 1}},
  87. }
  88.  
  89. local LIMB_ORDER_R6 = {"Head", "Torso", "Left Arm", "Right Arm", "Left Leg", "Right Leg"}
  90. local LIMB_ORDER_R15 = {
  91.     "Head", "UpperTorso", "LowerTorso",
  92.     "LeftUpperArm", "LeftLowerArm", "LeftHand",
  93.     "RightUpperArm", "RightLowerArm", "RightHand",
  94.     "LeftUpperLeg", "LeftLowerLeg", "LeftFoot",
  95.     "RightUpperLeg", "RightLowerLeg", "RightFoot"
  96. }
  97.  
  98. local EXCLUDED_PARTS = {
  99.     HumanoidRootPart = true,
  100.     RootPart = true
  101. }
  102.  
  103. local LIMB_DISPLAY_NAMES = {
  104.     Head = "Head", Torso = "Torso",
  105.     ["Left Arm"] = "L.Arm", ["Right Arm"] = "R.Arm",
  106.     ["Left Leg"] = "L.Leg", ["Right Leg"] = "R.Leg",
  107.     UpperTorso = "UpTorso", LowerTorso = "LoTorso",
  108.     LeftUpperArm = "L.UpArm", LeftLowerArm = "L.LoArm", LeftHand = "L.Hand",
  109.     RightUpperArm = "R.UpArm", RightLowerArm = "R.LoArm", RightHand = "R.Hand",
  110.     LeftUpperLeg = "L.UpLeg", LeftLowerLeg = "L.LoLeg", LeftFoot = "L.Foot",
  111.     RightUpperLeg = "R.UpLeg", RightLowerLeg = "R.LoLeg", RightFoot = "R.Foot"
  112. }
  113.  
  114. local R15_EXTENSION_CONFIG = {
  115.     Head = {sizeAdd = Vector3.new(0.4, 0.4, 0.4), offsetY = 0},
  116.     LeftHand = {sizeAdd = Vector3.new(0.6, 1.2, 0.6), offsetY = -0.6},
  117.     RightHand = {sizeAdd = Vector3.new(0.6, 1.2, 0.6), offsetY = -0.6},
  118.     LeftLowerArm = {sizeAdd = Vector3.new(0.6, 0.4, 0.6), offsetY = 0},
  119.     RightLowerArm = {sizeAdd = Vector3.new(0.6, 0.4, 0.6), offsetY = 0},
  120.     LeftUpperArm = {sizeAdd = Vector3.new(0.4, 0.3, 0.4), offsetY = 0},
  121.     RightUpperArm = {sizeAdd = Vector3.new(0.4, 0.3, 0.4), offsetY = 0},
  122.     LeftFoot = {sizeAdd = Vector3.new(0.5, 0.8, 1.2), offsetY = -0.4},
  123.     RightFoot = {sizeAdd = Vector3.new(0.5, 0.8, 1.2), offsetY = -0.4},
  124.     LeftLowerLeg = {sizeAdd = Vector3.new(0.5, 0.4, 0.5), offsetY = 0},
  125.     RightLowerLeg = {sizeAdd = Vector3.new(0.5, 0.4, 0.5), offsetY = 0},
  126.     LeftUpperLeg = {sizeAdd = Vector3.new(0.4, 0.3, 0.4), offsetY = 0},
  127.     RightUpperLeg = {sizeAdd = Vector3.new(0.4, 0.3, 0.4), offsetY = 0},
  128.     UpperTorso = {sizeAdd = Vector3.new(0.5, 0.3, 0.3), offsetY = 0},
  129.     LowerTorso = {sizeAdd = Vector3.new(0.4, 0.2, 0.3), offsetY = 0},
  130. }
  131.  
  132. local R6_EXTENSION_CONFIG = {
  133.     Head = {sizeAdd = Vector3.new(0.5, 0.5, 0.5), offsetY = 0},
  134.     Torso = {sizeAdd = Vector3.new(0.4, 0.3, 0.3), offsetY = 0},
  135.     ["Left Arm"] = {sizeAdd = Vector3.new(0.4, 0.4, 0.4), offsetY = 0},
  136.     ["Right Arm"] = {sizeAdd = Vector3.new(0.4, 0.4, 0.4), offsetY = 0},
  137.     ["Left Leg"] = {sizeAdd = Vector3.new(0.4, 0.4, 0.4), offsetY = 0},
  138.     ["Right Leg"] = {sizeAdd = Vector3.new(0.4, 0.4, 0.4), offsetY = 0},
  139. }
  140.  
  141. local PAPER_PHYSICS = PhysicalProperties.new(0.01, 0, 0, 0, 0)
  142.  
  143. local NanoPool = {
  144.     Attachments = {},
  145.     AlignPositions = {},
  146.     AlignOrientations = {},
  147.     Stats = {Created = 0, Reused = 0, FromNil = 0}
  148. }
  149.  
  150. function NanoPool.CollectFromNil()
  151.     for _, obj in ipairs(getnilinstances()) do
  152.         if obj.Name == "NanoPoolAtt" and obj:IsA("Attachment") then
  153.             if not table.find(NanoPool.Attachments, obj) then
  154.                 table.insert(NanoPool.Attachments, obj)
  155.                 NanoPool.Stats.FromNil = NanoPool.Stats.FromNil + 1
  156.             end
  157.         elseif obj.Name == "NanoPoolAP" and obj:IsA("AlignPosition") then
  158.             if not table.find(NanoPool.AlignPositions, obj) then
  159.                 table.insert(NanoPool.AlignPositions, obj)
  160.                 NanoPool.Stats.FromNil = NanoPool.Stats.FromNil + 1
  161.             end
  162.         elseif obj.Name == "NanoPoolAO" and obj:IsA("AlignOrientation") then
  163.             if not table.find(NanoPool.AlignOrientations, obj) then
  164.                 table.insert(NanoPool.AlignOrientations, obj)
  165.                 NanoPool.Stats.FromNil = NanoPool.Stats.FromNil + 1
  166.             end
  167.         end
  168.     end
  169. end
  170.  
  171. function NanoPool.Init()
  172.     NanoPool.CollectFromNil()
  173. end
  174.  
  175. function NanoPool.GetAttachment()
  176.     local att = table.remove(NanoPool.Attachments)
  177.     if att then
  178.         NanoPool.Stats.Reused = NanoPool.Stats.Reused + 1
  179.         return att
  180.     end
  181.     NanoPool.Stats.Created = NanoPool.Stats.Created + 1
  182.     local newAtt = Instance.new("Attachment")
  183.     newAtt.Name = "NanoPoolAtt"
  184.     return newAtt
  185. end
  186.  
  187. function NanoPool.GetAlignPosition()
  188.     local ap = table.remove(NanoPool.AlignPositions)
  189.     if ap then
  190.         NanoPool.Stats.Reused = NanoPool.Stats.Reused + 1
  191.         return ap
  192.     end
  193.     NanoPool.Stats.Created = NanoPool.Stats.Created + 1
  194.     local newAp = Instance.new("AlignPosition")
  195.     newAp.Name = "NanoPoolAP"
  196.     newAp.MaxForce = math.huge
  197.     newAp.MaxVelocity = math.huge
  198.     newAp.Responsiveness = 500
  199.     newAp.RigidityEnabled = true
  200.     return newAp
  201. end
  202.  
  203. function NanoPool.GetAlignOrientation()
  204.     local ao = table.remove(NanoPool.AlignOrientations)
  205.     if ao then
  206.         NanoPool.Stats.Reused = NanoPool.Stats.Reused + 1
  207.         return ao
  208.     end
  209.     NanoPool.Stats.Created = NanoPool.Stats.Created + 1
  210.     local newAo = Instance.new("AlignOrientation")
  211.     newAo.Name = "NanoPoolAO"
  212.     newAo.MaxTorque = math.huge
  213.     newAo.MaxAngularVelocity = math.huge
  214.     newAo.Responsiveness = 500
  215.     newAo.RigidityEnabled = true
  216.     return newAo
  217. end
  218.  
  219. function NanoPool.Return(item)
  220.     if not item then return end
  221.    
  222.     pcall(function() item.Parent = nil end)
  223.    
  224.     if item:IsA("Attachment") then
  225.         item.CFrame = CFrame.identity
  226.         table.insert(NanoPool.Attachments, item)
  227.     elseif item:IsA("AlignPosition") then
  228.         item.Attachment0 = nil
  229.         item.Attachment1 = nil
  230.         table.insert(NanoPool.AlignPositions, item)
  231.     elseif item:IsA("AlignOrientation") then
  232.         item.Attachment0 = nil
  233.         item.Attachment1 = nil
  234.         table.insert(NanoPool.AlignOrientations, item)
  235.     end
  236. end
  237.  
  238. function NanoPool.Clear()
  239.     for _, att in ipairs(NanoPool.Attachments) do
  240.         pcall(function() att:Destroy() end)
  241.     end
  242.     for _, ap in ipairs(NanoPool.AlignPositions) do
  243.         pcall(function() ap:Destroy() end)
  244.     end
  245.     for _, ao in ipairs(NanoPool.AlignOrientations) do
  246.         pcall(function() ao:Destroy() end)
  247.     end
  248.     NanoPool.Attachments = {}
  249.     NanoPool.AlignPositions = {}
  250.     NanoPool.AlignOrientations = {}
  251.     NanoPool.Stats = {Created = 0, Reused = 0, FromNil = 0}
  252. end
  253.  
  254. local NanoMath = {}
  255.  
  256. function NanoMath.GetRotatedSize(size, rotationData)
  257.     local order = rotationData.order
  258.     local dims = {size.X, size.Y, size.Z}
  259.     return Vector3.new(dims[order[1]], dims[order[2]], dims[order[3]])
  260. end
  261.  
  262. function NanoMath.PartSizeToGridCells(partSize, cellSize)
  263.     local cx = math.max(1, math.ceil(partSize.X / cellSize))
  264.     local cy = math.max(1, math.ceil(partSize.Y / cellSize))
  265.     local cz = math.max(1, math.ceil(partSize.Z / cellSize))
  266.     return cx, cy, cz
  267. end
  268.  
  269. local NanoGui = {
  270.     Cache = {},
  271.     DebugGui = nil,
  272.     DebugFrame = nil,
  273.     DebugLabel = nil,
  274.     LimbsLabel = nil,
  275.     Enabled = false,
  276.     Minimized = false,
  277.     LastUpdate = 0,
  278.     Dragging = false,
  279.     DragStart = nil,
  280.     FrameStart = nil,
  281.     DragConnection = nil,
  282.     FullHeight = 500,
  283.     MinHeight = 28,
  284.     LastDebugText = "",
  285.     LastLimbsText = ""
  286. }
  287.  
  288. function NanoGui.CleanupDuplicates()
  289.     pcall(function()
  290.         for _, gui in ipairs(CoreGui:GetChildren()) do
  291.             if gui.Name == "NanoDebugGui" then gui:Destroy() end
  292.         end
  293.     end)
  294.     pcall(function()
  295.         local pg = LocalPlayer:FindFirstChild("PlayerGui")
  296.         if pg then
  297.             for _, gui in ipairs(pg:GetChildren()) do
  298.                 if gui.Name == "NanoDebugGui" then gui:Destroy() end
  299.             end
  300.         end
  301.     end)
  302. end
  303.  
  304. function NanoGui.SaveState()
  305.     NanoGui.Cache = {}
  306.     local playerGui = LocalPlayer:FindFirstChild("PlayerGui")
  307.     if not playerGui then return end
  308.     for _, gui in ipairs(playerGui:GetChildren()) do
  309.         if gui:IsA("ScreenGui") then
  310.             NanoGui.Cache[gui.Name] = {Enabled = gui.Enabled, ResetOnSpawn = gui.ResetOnSpawn}
  311.         end
  312.     end
  313. end
  314.  
  315. function NanoGui.RestoreState()
  316.     local playerGui = LocalPlayer:FindFirstChild("PlayerGui")
  317.     if not playerGui then return end
  318.     for name, state in pairs(NanoGui.Cache) do
  319.         local gui = playerGui:FindFirstChild(name)
  320.         if gui and gui:IsA("ScreenGui") then
  321.             pcall(function() gui.Enabled = state.Enabled end)
  322.         end
  323.     end
  324. end
  325.  
  326. function NanoGui.CopyInfo(Runtime, CFG)
  327.     if not setclipboard then
  328.         StarterGui:SetCore("SendNotification", {
  329.             Title = "NanoMech",
  330.             Text = "Clipboard not supported!",
  331.             Duration = 2
  332.         })
  333.         return
  334.     end
  335.    
  336.     local info = "=== NANO-MECH v3.6 DEBUG INFO ===\n\n"
  337.     info = info .. "=== GENERAL ===\n"
  338.     info = info .. NanoGui.LastDebugText .. "\n\n"
  339.     info = info .. "=== LIMBS ===\n"
  340.     info = info .. NanoGui.LastLimbsText .. "\n\n"
  341.     info = info .. "=== POOL STATS ===\n"
  342.     info = info .. string.format("Attachments in pool: %d\n", #NanoPool.Attachments)
  343.     info = info .. string.format("AlignPositions in pool: %d\n", #NanoPool.AlignPositions)
  344.     info = info .. string.format("AlignOrientations in pool: %d\n", #NanoPool.AlignOrientations)
  345.     info = info .. string.format("Created: %d | Reused: %d | FromNil: %d\n",
  346.         NanoPool.Stats.Created, NanoPool.Stats.Reused, NanoPool.Stats.FromNil)
  347.     info = info .. "\n=== CONFIG ===\n"
  348.     info = info .. string.format("MechScale: %.1f\n", CFG.MechScale)
  349.     info = info .. string.format("MechType: %s\n", CFG.MechType)
  350.     info = info .. string.format("FakeRig: %s\n", CFG.FakeRig)
  351.     info = info .. string.format("CellSize: %.2f (auto: %.2f)\n", CFG.CellSize, CFG.CellSize * CFG.MechScale)
  352.     info = info .. string.format("ScanRadius: %d\n", CFG.ScanRadius)
  353.     info = info .. string.format("MaxParts: %d\n", CFG.MaxParts)
  354.     info = info .. "\n=== TRACKED PARTS ===\n"
  355.    
  356.     local limbCounts = {}
  357.     for part, data in pairs(Runtime.TrackedParts or {}) do
  358.         local limb = data.limbName or "Unknown"
  359.         limbCounts[limb] = (limbCounts[limb] or 0) + 1
  360.     end
  361.     for limb, count in pairs(limbCounts) do
  362.         info = info .. string.format("%s: %d parts\n", limb, count)
  363.     end
  364.    
  365.     info = info .. "\n=== TIMESTAMP ===\n"
  366.     info = info .. os.date("%Y-%m-%d %H:%M:%S")
  367.    
  368.     setclipboard(info)
  369.    
  370.     StarterGui:SetCore("SendNotification", {
  371.         Title = "NanoMech",
  372.         Text = "Debug info copied to clipboard!",
  373.         Duration = 2
  374.     })
  375. end
  376.  
  377. function NanoGui.CreateDebug(Runtime, CFG)
  378.     NanoGui.CleanupDuplicates()
  379.    
  380.     local sg = Instance.new("ScreenGui")
  381.     sg.Name = "NanoDebugGui"
  382.     sg.IgnoreGuiInset = true
  383.     sg.ResetOnSpawn = false
  384.     sg.DisplayOrder = 999
  385.    
  386.     pcall(function() sg.Parent = CoreGui end)
  387.     if not sg.Parent then
  388.         pcall(function() sg.Parent = LocalPlayer:WaitForChild("PlayerGui") end)
  389.     end
  390.    
  391.     local frame = Instance.new("Frame")
  392.     frame.Name = "DebugFrame"
  393.     frame.Size = UDim2.new(0, 260, 0, NanoGui.FullHeight)
  394.     frame.Position = UDim2.new(0, 10, 0, 10)
  395.     frame.BackgroundColor3 = Color3.fromRGB(15, 15, 15)
  396.     frame.BackgroundTransparency = 0.05
  397.     frame.BorderSizePixel = 0
  398.     frame.Active = true
  399.     frame.ClipsDescendants = true
  400.     frame.Parent = sg
  401.    
  402.     local corner = Instance.new("UICorner")
  403.     corner.CornerRadius = UDim.new(0, 8)
  404.     corner.Parent = frame
  405.    
  406.     local stroke = Instance.new("UIStroke")
  407.     stroke.Color = Color3.fromRGB(0, 255, 100)
  408.     stroke.Thickness = 2
  409.     stroke.Parent = frame
  410.    
  411.     local titleBar = Instance.new("Frame")
  412.     titleBar.Name = "TitleBar"
  413.     titleBar.Size = UDim2.new(1, 0, 0, 28)
  414.     titleBar.BackgroundColor3 = Color3.fromRGB(0, 180, 80)
  415.     titleBar.BackgroundTransparency = 0.2
  416.     titleBar.BorderSizePixel = 0
  417.     titleBar.Parent = frame
  418.    
  419.     local titleCorner = Instance.new("UICorner")
  420.     titleCorner.CornerRadius = UDim.new(0, 8)
  421.     titleCorner.Parent = titleBar
  422.    
  423.     local titleFix = Instance.new("Frame")
  424.     titleFix.Size = UDim2.new(1, 0, 0, 10)
  425.     titleFix.Position = UDim2.new(0, 0, 1, -10)
  426.     titleFix.BackgroundColor3 = Color3.fromRGB(0, 180, 80)
  427.     titleFix.BackgroundTransparency = 0.2
  428.     titleFix.BorderSizePixel = 0
  429.     titleFix.Parent = titleBar
  430.    
  431.     local titleLabel = Instance.new("TextLabel")
  432.     titleLabel.Size = UDim2.new(1, -130, 1, 0)
  433.     titleLabel.Position = UDim2.new(0, 10, 0, 0)
  434.     titleLabel.BackgroundTransparency = 1
  435.     titleLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
  436.     titleLabel.TextSize = 14
  437.     titleLabel.Font = Enum.Font.GothamBold
  438.     titleLabel.Text = "NANO-MECH v3.6"
  439.     titleLabel.TextXAlignment = Enum.TextXAlignment.Left
  440.     titleLabel.Parent = titleBar
  441.    
  442.     local function createButton(name, text, color, posX, width)
  443.         local btn = Instance.new("TextButton")
  444.         btn.Name = name
  445.         btn.Size = UDim2.new(0, width or 24, 0, 20)
  446.         btn.Position = UDim2.new(1, posX, 0, 4)
  447.         btn.BackgroundColor3 = color
  448.         btn.BackgroundTransparency = 0.3
  449.         btn.BorderSizePixel = 0
  450.         btn.TextColor3 = Color3.fromRGB(255, 255, 255)
  451.         btn.TextSize = 10
  452.         btn.Font = Enum.Font.GothamBold
  453.         btn.Text = text
  454.         btn.Parent = titleBar
  455.        
  456.         local btnCorner = Instance.new("UICorner")
  457.         btnCorner.CornerRadius = UDim.new(0, 4)
  458.         btnCorner.Parent = btn
  459.        
  460.         return btn
  461.     end
  462.    
  463.     local closeBtn = createButton("CloseBtn", "X", Color3.fromRGB(255, 60, 60), -30, 24)
  464.     local minBtn = createButton("MinBtn", "-", Color3.fromRGB(255, 180, 0), -58, 24)
  465.     local copyBtn = createButton("CopyBtn", "COPY", Color3.fromRGB(0, 150, 255), -105, 42)
  466.    
  467.     closeBtn.MouseButton1Click:Connect(function()
  468.         NanoGui.DestroyDebug()
  469.     end)
  470.    
  471.     minBtn.MouseButton1Click:Connect(function()
  472.         NanoGui.Minimized = not NanoGui.Minimized
  473.         if NanoGui.Minimized then
  474.             frame.Size = UDim2.new(0, 260, 0, NanoGui.MinHeight)
  475.             minBtn.Text = "+"
  476.         else
  477.             frame.Size = UDim2.new(0, 260, 0, NanoGui.FullHeight)
  478.             minBtn.Text = "-"
  479.         end
  480.     end)
  481.    
  482.     copyBtn.MouseButton1Click:Connect(function()
  483.         NanoGui.CopyInfo(Runtime, CFG)
  484.     end)
  485.    
  486.     local contentFrame = Instance.new("Frame")
  487.     contentFrame.Name = "Content"
  488.     contentFrame.Size = UDim2.new(1, -12, 1, -36)
  489.     contentFrame.Position = UDim2.new(0, 6, 0, 32)
  490.     contentFrame.BackgroundTransparency = 1
  491.     contentFrame.Parent = frame
  492.    
  493.     local statsLabel = Instance.new("TextLabel")
  494.     statsLabel.Name = "Stats"
  495.     statsLabel.Size = UDim2.new(1, 0, 0, 200)
  496.     statsLabel.Position = UDim2.new(0, 0, 0, 0)
  497.     statsLabel.BackgroundTransparency = 1
  498.     statsLabel.TextColor3 = Color3.fromRGB(0, 255, 100)
  499.     statsLabel.TextSize = 11
  500.     statsLabel.Font = Enum.Font.Code
  501.     statsLabel.TextXAlignment = Enum.TextXAlignment.Left
  502.     statsLabel.TextYAlignment = Enum.TextYAlignment.Top
  503.     statsLabel.Text = "Loading..."
  504.     statsLabel.Parent = contentFrame
  505.    
  506.     local limbsLabel = Instance.new("TextLabel")
  507.     limbsLabel.Name = "Limbs"
  508.     limbsLabel.Size = UDim2.new(1, 0, 0, 260)
  509.     limbsLabel.Position = UDim2.new(0, 0, 0, 205)
  510.     limbsLabel.BackgroundTransparency = 1
  511.     limbsLabel.TextColor3 = Color3.fromRGB(100, 255, 150)
  512.     limbsLabel.TextSize = 10
  513.     limbsLabel.Font = Enum.Font.Code
  514.     limbsLabel.TextXAlignment = Enum.TextXAlignment.Left
  515.     limbsLabel.TextYAlignment = Enum.TextYAlignment.Top
  516.     limbsLabel.Text = ""
  517.     limbsLabel.Parent = contentFrame
  518.    
  519.     titleBar.InputBegan:Connect(function(input)
  520.         if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
  521.             NanoGui.Dragging = true
  522.             NanoGui.DragStart = input.Position
  523.             NanoGui.FrameStart = frame.Position
  524.         end
  525.     end)
  526.    
  527.     titleBar.InputEnded:Connect(function(input)
  528.         if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
  529.             NanoGui.Dragging = false
  530.         end
  531.     end)
  532.    
  533.     if NanoGui.DragConnection then NanoGui.DragConnection:Disconnect() end
  534.     NanoGui.DragConnection = UserInputService.InputChanged:Connect(function(input)
  535.         if NanoGui.Dragging and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
  536.             local delta = input.Position - NanoGui.DragStart
  537.             frame.Position = UDim2.new(NanoGui.FrameStart.X.Scale, NanoGui.FrameStart.X.Offset + delta.X, NanoGui.FrameStart.Y.Scale, NanoGui.FrameStart.Y.Offset + delta.Y)
  538.         end
  539.     end)
  540.    
  541.     NanoGui.DebugGui = sg
  542.     NanoGui.DebugFrame = frame
  543.     NanoGui.DebugLabel = statsLabel
  544.     NanoGui.LimbsLabel = limbsLabel
  545.     NanoGui.Enabled = true
  546.     NanoGui.Minimized = false
  547. end
  548.  
  549. function NanoGui.UpdateDebug(Runtime, CFG)
  550.     if not NanoGui.Enabled or not NanoGui.DebugLabel or NanoGui.Minimized then return end
  551.    
  552.     local now = tick()
  553.     if now - NanoGui.LastUpdate < 0.4 then return end
  554.     NanoGui.LastUpdate = now
  555.    
  556.     local trackedCount = 0
  557.     for _ in pairs(Runtime.TrackedParts or {}) do trackedCount = trackedCount + 1 end
  558.    
  559.     local totalCells, occupiedCells = 0, 0
  560.     local limbStats = {}
  561.     local limbPartCounts = {}
  562.    
  563.     local limbOrder = Runtime.FakeRigType == "R15" and LIMB_ORDER_R15 or LIMB_ORDER_R6
  564.    
  565.     for _, limbName in ipairs(limbOrder) do
  566.         local grid = Runtime.LimbGrids[limbName]
  567.         if grid and grid.occupancy then
  568.             local t, o = 0, 0
  569.             local partCount = 0
  570.             local countedParts = {}
  571.            
  572.             for x = 0, grid.gridSize.X - 1 do
  573.                 for y = 0, grid.gridSize.Y - 1 do
  574.                     for z = 0, grid.gridSize.Z - 1 do
  575.                         if grid.occupancy[x] and grid.occupancy[x][y] then
  576.                             if grid.partMap[x][y][z] ~= "INVALID" then
  577.                                 totalCells = totalCells + 1
  578.                                 t = t + 1
  579.                                 if grid.occupancy[x][y][z] then
  580.                                     occupiedCells = occupiedCells + 1
  581.                                     o = o + 1
  582.                                     local part = grid.partMap[x][y][z]
  583.                                     if part and not countedParts[part] then
  584.                                         countedParts[part] = true
  585.                                         partCount = partCount + 1
  586.                                     end
  587.                                 end
  588.                             end
  589.                         end
  590.                     end
  591.                 end
  592.             end
  593.             limbStats[limbName] = {total = t, occupied = o}
  594.             limbPartCounts[limbName] = partCount
  595.         end
  596.     end
  597.    
  598.     local state = Runtime.IsDead and "DEAD" or (Runtime.IsRunning and "RUNNING" or "IDLE")
  599.     local fillPercent = totalCells > 0 and math.floor((occupiedCells / totalCells) * 100) or 0
  600.     local fillBar = string.rep("ā–ˆ", math.floor(fillPercent / 5)) .. string.rep("ā–‘", 20 - math.floor(fillPercent / 5))
  601.    
  602.     local poolTotal = #NanoPool.Attachments + #NanoPool.AlignPositions + #NanoPool.AlignOrientations
  603.     local effectiveCellSize = CFG.CellSize * CFG.MechScale
  604.    
  605.     local debugText = string.format(
  606.         "STATE:  %s\n" ..
  607.         "TYPE:   %s\n" ..
  608.         "RIG:    %s → %s\n" ..
  609.         "────────────────────────\n" ..
  610.         "PARTS:  %d / %d (scanned: %d)\n" ..
  611.         "CELLS:  %d / %d\n" ..
  612.         "FILL:   %s %d%%\n" ..
  613.         "────────────────────────\n" ..
  614.         "JUMP:   %s | GND: %s\n" ..
  615.         "SCALE:  %.1fx | CELL: %.2f\n" ..
  616.         "────────────────────────\n" ..
  617.         "POOL:   %d available\n" ..
  618.         "NEW: %d | RE: %d | NIL: %d\n" ..
  619.         "────────────────────────\n" ..
  620.         "PENDING: %d",
  621.         state, CFG.MechType or "Full",
  622.         Runtime.RealRigType or "?", Runtime.FakeRigType or "?",
  623.         trackedCount, CFG.MaxParts or 512, Runtime.ScannedPartsCount or 0,
  624.         occupiedCells, totalCells, fillBar, fillPercent,
  625.         Runtime.JumpState or "?", Runtime.IsGrounded and "Y" or "N",
  626.         CFG.MechScale or 1, effectiveCellSize,
  627.         poolTotal,
  628.         NanoPool.Stats.Created, NanoPool.Stats.Reused, NanoPool.Stats.FromNil,
  629.         Runtime.PendingPartsCount or 0
  630.     )
  631.    
  632.     NanoGui.DebugLabel.Text = debugText
  633.     NanoGui.LastDebugText = debugText
  634.    
  635.     local limbLines = {"────────────────────────", "LIMBS:      FILL    PCS"}
  636.     for _, limbName in ipairs(limbOrder) do
  637.         local stats = limbStats[limbName]
  638.         local partCount = limbPartCounts[limbName] or 0
  639.         if stats then
  640.             local pct = stats.total > 0 and math.floor((stats.occupied / stats.total) * 100) or 0
  641.             local displayName = LIMB_DISPLAY_NAMES[limbName] or limbName
  642.             local bar = string.rep("ā–ˆ", math.floor(pct / 10)) .. string.rep("ā–‘", 10 - math.floor(pct / 10))
  643.             table.insert(limbLines, string.format("%-8s %s %3d%% %2d", displayName, bar, pct, partCount))
  644.         end
  645.     end
  646.    
  647.     local limbsText = table.concat(limbLines, "\n")
  648.     if NanoGui.LimbsLabel then
  649.         NanoGui.LimbsLabel.Text = limbsText
  650.     end
  651.     NanoGui.LastLimbsText = limbsText
  652. end
  653.  
  654. function NanoGui.DestroyDebug()
  655.     if NanoGui.DragConnection then NanoGui.DragConnection:Disconnect() NanoGui.DragConnection = nil end
  656.     if NanoGui.DebugGui then pcall(function() NanoGui.DebugGui:Destroy() end) end
  657.     NanoGui.DebugGui = nil
  658.     NanoGui.DebugFrame = nil
  659.     NanoGui.DebugLabel = nil
  660.     NanoGui.LimbsLabel = nil
  661.     NanoGui.Enabled = false
  662.     NanoGui.Dragging = false
  663.     NanoGui.Minimized = false
  664. end
  665.  
  666. local NanoGrid = {}
  667.  
  668. function NanoGrid.Create(limbPart, cellSize, mechType, limbName, extensionConfig)
  669.     local baseSize = limbPart.Size
  670.     local size = baseSize
  671.     local offsetY = 0
  672.    
  673.     if extensionConfig and extensionConfig[limbName] then
  674.         local ext = extensionConfig[limbName]
  675.         size = baseSize + ext.sizeAdd
  676.         offsetY = ext.offsetY or 0
  677.     end
  678.    
  679.     local gridSizeX = math.max(1, math.ceil(size.X / cellSize))
  680.     local gridSizeY = math.max(1, math.ceil(size.Y / cellSize))
  681.     local gridSizeZ = math.max(1, math.ceil(size.Z / cellSize))
  682.    
  683.     local grid = {
  684.         bodyPart = limbPart,
  685.         cellSize = cellSize,
  686.         gridSize = Vector3.new(gridSizeX, gridSizeY, gridSizeZ),
  687.         baseSize = baseSize,
  688.         extendedSize = size,
  689.         offsetY = offsetY,
  690.         occupancy = {},
  691.         partMap = {},
  692.         totalCells = 0,
  693.         validCells = 0
  694.     }
  695.    
  696.     local centerX = (gridSizeX - 1) / 2
  697.     local centerY = (gridSizeY - 1) / 2
  698.     local centerZ = (gridSizeZ - 1) / 2
  699.    
  700.     local isHead = limbName == "Head"
  701.    
  702.     for x = 0, gridSizeX - 1 do
  703.         grid.occupancy[x] = {}
  704.         grid.partMap[x] = {}
  705.         for y = 0, gridSizeY - 1 do
  706.             grid.occupancy[x][y] = {}
  707.             grid.partMap[x][y] = {}
  708.             for z = 0, gridSizeZ - 1 do
  709.                 grid.totalCells = grid.totalCells + 1
  710.                 local isValid = true
  711.                
  712.                 if isHead then
  713.                     local distX = math.abs(x - centerX) / math.max(1, centerX)
  714.                     local distY = math.abs(y - centerY) / math.max(1, centerY)
  715.                     local distZ = math.abs(z - centerZ) / math.max(1, centerZ)
  716.                     local sphereDist = math.sqrt(distX * distX + distY * distY + distZ * distZ)
  717.                     isValid = sphereDist <= 1.2
  718.                 elseif mechType == "Hollow" then
  719.                     local nx = gridSizeX > 1 and (x - centerX) / centerX or 0
  720.                     local nz = gridSizeZ > 1 and (z - centerZ) / centerZ or 0
  721.                     local dist = math.sqrt(nx * nx + nz * nz)
  722.                     isValid = dist >= 0.5
  723.                 elseif mechType == "Skeleton" then
  724.                     local threshX = math.max(1, gridSizeX * 0.2)
  725.                     local threshY = math.max(1, gridSizeY * 0.2)
  726.                     local threshZ = math.max(1, gridSizeZ * 0.2)
  727.                     local onX = math.abs(y - centerY) <= threshY and math.abs(z - centerZ) <= threshZ
  728.                     local onY = math.abs(x - centerX) <= threshX and math.abs(z - centerZ) <= threshZ
  729.                     local onZ = math.abs(x - centerX) <= threshX and math.abs(y - centerY) <= threshY
  730.                     isValid = onX or onY or onZ
  731.                 elseif mechType == "Armor" then
  732.                     local margin = math.max(1, math.min(gridSizeX, gridSizeY, gridSizeZ) * 0.3)
  733.                     local isOuterX = x < margin or x >= gridSizeX - margin
  734.                     local isOuterY = y < margin or y >= gridSizeY - margin
  735.                     local isOuterZ = z < margin or z >= gridSizeZ - margin
  736.                     isValid = isOuterX or isOuterY or isOuterZ
  737.                 end
  738.                
  739.                 if isValid then
  740.                     grid.occupancy[x][y][z] = false
  741.                     grid.partMap[x][y][z] = nil
  742.                     grid.validCells = grid.validCells + 1
  743.                 else
  744.                     grid.occupancy[x][y][z] = true
  745.                     grid.partMap[x][y][z] = "INVALID"
  746.                 end
  747.             end
  748.         end
  749.     end
  750.    
  751.     return grid
  752. end
  753.  
  754. function NanoGrid.IsAreaFree(grid, startX, startY, startZ, sizeX, sizeY, sizeZ)
  755.     local gs = grid.gridSize
  756.    
  757.     if startX < 0 or startY < 0 or startZ < 0 then return false end
  758.     if startX + sizeX > gs.X or startY + sizeY > gs.Y or startZ + sizeZ > gs.Z then return false end
  759.    
  760.     for x = startX, startX + sizeX - 1 do
  761.         for y = startY, startY + sizeY - 1 do
  762.             for z = startZ, startZ + sizeZ - 1 do
  763.                 if grid.occupancy[x] and grid.occupancy[x][y] and grid.occupancy[x][y][z] then
  764.                     return false
  765.                 end
  766.             end
  767.         end
  768.     end
  769.    
  770.     return true
  771. end
  772.  
  773. function NanoGrid.GetNeighborScore(grid, startX, startY, startZ, sizeX, sizeY, sizeZ)
  774.     local score = 0
  775.     local gs = grid.gridSize
  776.     local checked = {}
  777.    
  778.     local directions = {
  779.         {-1, 0, 0}, {1, 0, 0},
  780.         {0, -1, 0}, {0, 1, 0},
  781.         {0, 0, -1}, {0, 0, 1}
  782.     }
  783.    
  784.     for x = startX, startX + sizeX - 1 do
  785.         for y = startY, startY + sizeY - 1 do
  786.             for z = startZ, startZ + sizeZ - 1 do
  787.                 for _, dir in ipairs(directions) do
  788.                     local nx, ny, nz = x + dir[1], y + dir[2], z + dir[3]
  789.                    
  790.                     if nx >= startX and nx < startX + sizeX and
  791.                        ny >= startY and ny < startY + sizeY and
  792.                        nz >= startZ and nz < startZ + sizeZ then
  793.                         continue
  794.                     end
  795.                    
  796.                     local key = nx .. "_" .. ny .. "_" .. nz
  797.                     if checked[key] then continue end
  798.                     checked[key] = true
  799.                    
  800.                     if nx >= 0 and nx < gs.X and ny >= 0 and ny < gs.Y and nz >= 0 and nz < gs.Z then
  801.                         if grid.occupancy[nx] and grid.occupancy[nx][ny] and grid.occupancy[nx][ny][nz] then
  802.                             if grid.partMap[nx][ny][nz] and grid.partMap[nx][ny][nz] ~= "INVALID" then
  803.                                 score = score + 1
  804.                             end
  805.                         end
  806.                     end
  807.                 end
  808.             end
  809.         end
  810.     end
  811.    
  812.     return score
  813. end
  814.  
  815. function NanoGrid.FindBestPlacement(grid, partSize, usePriority)
  816.     local cellSize = grid.cellSize
  817.     local gs = grid.gridSize
  818.    
  819.     local bestPos = nil
  820.     local bestRot = nil
  821.     local bestScore = -math.huge
  822.     local bestCells = nil
  823.    
  824.     for _, rotData in ipairs(ROTATIONS) do
  825.         local rotatedSize = NanoMath.GetRotatedSize(partSize, rotData)
  826.         local cellsX, cellsY, cellsZ = NanoMath.PartSizeToGridCells(rotatedSize, cellSize)
  827.        
  828.         if cellsX > gs.X or cellsY > gs.Y or cellsZ > gs.Z then
  829.             continue
  830.         end
  831.        
  832.         for x = 0, gs.X - cellsX do
  833.             for y = 0, gs.Y - cellsY do
  834.                 for z = 0, gs.Z - cellsZ do
  835.                     if NanoGrid.IsAreaFree(grid, x, y, z, cellsX, cellsY, cellsZ) then
  836.                         local score = 0
  837.                        
  838.                         if usePriority then
  839.                             score = score + NanoGrid.GetNeighborScore(grid, x, y, z, cellsX, cellsY, cellsZ) * 10
  840.                         end
  841.                        
  842.                         local centerX = gs.X / 2
  843.                         local centerZ = gs.Z / 2
  844.                         local distFromCenter = math.sqrt((x + cellsX/2 - centerX)^2 + (z + cellsZ/2 - centerZ)^2)
  845.                         score = score - distFromCenter
  846.                         score = score + y * 0.5
  847.                        
  848.                         local volume = cellsX * cellsY * cellsZ
  849.                         score = score + volume * 0.1
  850.                        
  851.                         if score > bestScore then
  852.                             bestScore = score
  853.                             bestPos = Vector3.new(x, y, z)
  854.                             bestRot = rotData
  855.                             bestCells = Vector3.new(cellsX, cellsY, cellsZ)
  856.                         end
  857.                     end
  858.                 end
  859.             end
  860.         end
  861.     end
  862.    
  863.     return bestPos, bestRot, bestCells, bestScore
  864. end
  865.  
  866. function NanoGrid.MarkAreaOccupied(grid, startX, startY, startZ, sizeX, sizeY, sizeZ, part)
  867.     for x = startX, startX + sizeX - 1 do
  868.         for y = startY, startY + sizeY - 1 do
  869.             for z = startZ, startZ + sizeZ - 1 do
  870.                 if grid.occupancy[x] and grid.occupancy[x][y] then
  871.                     grid.occupancy[x][y][z] = true
  872.                     grid.partMap[x][y][z] = part
  873.                 end
  874.             end
  875.         end
  876.     end
  877. end
  878.  
  879. function NanoGrid.MarkAreaFree(grid, startX, startY, startZ, sizeX, sizeY, sizeZ)
  880.     for x = startX, startX + sizeX - 1 do
  881.         for y = startY, startY + sizeY - 1 do
  882.             for z = startZ, startZ + sizeZ - 1 do
  883.                 if grid.occupancy[x] and grid.occupancy[x][y] then
  884.                     if grid.partMap[x][y][z] ~= "INVALID" then
  885.                         grid.occupancy[x][y][z] = false
  886.                         grid.partMap[x][y][z] = nil
  887.                     end
  888.                 end
  889.             end
  890.         end
  891.     end
  892. end
  893.  
  894. function NanoGrid.GetWorldOffset(grid, gridPos, cellsSize)
  895.     local cellSize = grid.cellSize
  896.     local gs = grid.gridSize
  897.    
  898.     local offsetX = (gridPos.X + cellsSize.X / 2 - gs.X / 2) * cellSize
  899.     local offsetY = (gridPos.Y + cellsSize.Y / 2 - gs.Y / 2) * cellSize + (grid.offsetY or 0)
  900.     local offsetZ = (gridPos.Z + cellsSize.Z / 2 - gs.Z / 2) * cellSize
  901.    
  902.     return Vector3.new(offsetX, offsetY, offsetZ)
  903. end
  904.  
  905. local NanoPhysics = {}
  906.  
  907. function NanoPhysics.CreateAlignMovers(part, limbPart, worldOffset, rotation)
  908.     local attach = NanoPool.GetAttachment()
  909.     attach.CFrame = CFrame.new(worldOffset) * rotation
  910.     attach.Parent = limbPart
  911.    
  912.     local partAttach = NanoPool.GetAttachment()
  913.     partAttach.Parent = part
  914.    
  915.     local ap = NanoPool.GetAlignPosition()
  916.     ap.Attachment0 = partAttach
  917.     ap.Attachment1 = attach
  918.     ap.Parent = part
  919.    
  920.     local ao = NanoPool.GetAlignOrientation()
  921.     ao.Attachment0 = partAttach
  922.     ao.Attachment1 = attach
  923.     ao.Parent = part
  924.    
  925.     return {
  926.         position = ap,
  927.         orientation = ao,
  928.         limbAttachment = attach,
  929.         partAttachment = partAttach
  930.     }
  931. end
  932.  
  933. function NanoPhysics.ReturnMovers(movers)
  934.     if not movers then return end
  935.     if movers.position then NanoPool.Return(movers.position) end
  936.     if movers.orientation then NanoPool.Return(movers.orientation) end
  937.     if movers.limbAttachment then NanoPool.Return(movers.limbAttachment) end
  938.     if movers.partAttachment then NanoPool.Return(movers.partAttachment) end
  939. end
  940.  
  941. function NanoPhysics.ApplyAntisleep(part, CFG, LocalPlayer)
  942.     if not CFG.AntisleepEnabled then return end
  943.    
  944.     pcall(function()
  945.         local isSleeping = false
  946.         pcall(function()
  947.             isSleeping = part:GetNetworkOwner() == LocalPlayer and part.AssemblyLinearVelocity.Magnitude < 0.01
  948.         end)
  949.        
  950.         if isSleeping or part.AssemblyLinearVelocity.Magnitude < 0.01 then
  951.             local vel = CFG.AntisleepVelocity
  952.             part.AssemblyLinearVelocity = part.AssemblyLinearVelocity + Vector3.new(
  953.                 (math.random() - 0.5) * vel * 2,
  954.                 (math.random() - 0.5) * vel * 2,
  955.                 (math.random() - 0.5) * vel * 2
  956.             )
  957.         end
  958.     end)
  959.    
  960.     pcall(function()
  961.         sethidden(part, "NetworkIsSleeping", false)
  962.     end)
  963. end
  964.  
  965. local NanoCharacter = {}
  966.  
  967. function NanoCharacter.GetRigType(char)
  968.     if not char then return nil end
  969.     local humanoid = char:FindFirstChildOfClass("Humanoid")
  970.     if not humanoid then return nil end
  971.     return humanoid.RigType == Enum.HumanoidRigType.R15 and "R15" or "R6"
  972. end
  973.  
  974. function NanoCharacter.NormalizeRig(value)
  975.     if value == nil then return "R6" end
  976.     if type(value) == "string" and string.find(string.lower(value), "15") then
  977.         return "R15"
  978.     end
  979.     return "R6"
  980. end
  981.  
  982. function NanoCharacter.StopAllAnimations(char)
  983.     if not char then return end
  984.    
  985.     local animate = char:FindFirstChild("Animate")
  986.     if animate then animate.Disabled = true end
  987.    
  988.     local humanoid = char:FindFirstChildOfClass("Humanoid")
  989.     if humanoid then
  990.         local animator = humanoid:FindFirstChildOfClass("Animator")
  991.         if animator then
  992.             for _, track in ipairs(animator:GetPlayingAnimationTracks()) do
  993.                 pcall(function() track:Stop(0) end)
  994.             end
  995.         end
  996.         for _, track in ipairs(humanoid:GetPlayingAnimationTracks()) do
  997.             pcall(function() track:Stop(0) end)
  998.         end
  999.     end
  1000. end
  1001.  
  1002. function NanoCharacter.RestoreAnimations(char)
  1003.     if not char then return end
  1004.     local animate = char:FindFirstChild("Animate")
  1005.     if animate then
  1006.         animate.Disabled = true
  1007.         task.wait(0.1)
  1008.         animate.Disabled = false
  1009.     end
  1010. end
  1011.  
  1012. function NanoCharacter.HasTouchInterest(instance)
  1013.     for _, child in ipairs(instance:GetDescendants()) do
  1014.         if child:IsA("TouchTransmitter") or child.ClassName == "TouchInterest" then
  1015.             return true
  1016.         end
  1017.     end
  1018.     return false
  1019. end
  1020.  
  1021. function NanoCharacter.DisableTouchOnCharacter(char)
  1022.     if not char then return end
  1023.     for _, part in ipairs(char:GetDescendants()) do
  1024.         if part:IsA("BasePart") then
  1025.             pcall(function() part.CanTouch = false end)
  1026.         end
  1027.     end
  1028. end
  1029.  
  1030. function NanoCharacter.CreateFake(realChar, targetRig, CFG)
  1031.     if not realChar then return nil end
  1032.    
  1033.     local realHRP = realChar:FindFirstChild("HumanoidRootPart")
  1034.     if not realHRP then return nil end
  1035.    
  1036.     local realRig = NanoCharacter.GetRigType(realChar)
  1037.     local fakeRig = NanoCharacter.NormalizeRig(targetRig)
  1038.    
  1039.     local fake = nil
  1040.    
  1041.     if realRig == fakeRig then
  1042.         pcall(function()
  1043.             realChar.Archivable = true
  1044.             fake = realChar:Clone()
  1045.             realChar.Archivable = false
  1046.         end)
  1047.     else
  1048.         pcall(function()
  1049.             local rigType = fakeRig == "R6" and Enum.HumanoidRigType.R6 or Enum.HumanoidRigType.R15
  1050.             local desc = Players:GetHumanoidDescriptionFromUserId(LocalPlayer.UserId)
  1051.             fake = Players:CreateHumanoidModelFromDescription(desc, rigType)
  1052.         end)
  1053.     end
  1054.    
  1055.     if not fake then return nil end
  1056.    
  1057.     for _, desc in ipairs(fake:GetDescendants()) do
  1058.         if desc:IsA("Script") or desc:IsA("LocalScript") then
  1059.             if desc.Name ~= "Animate" and desc.Name ~= "Health" then
  1060.                 desc:Destroy()
  1061.             end
  1062.         end
  1063.     end
  1064.    
  1065.     for _, child in ipairs(fake:GetChildren()) do
  1066.         if child:IsA("Accessory") then child:Destroy() end
  1067.     end
  1068.    
  1069.     local transparency = CFG.MechType == "Skeleton" and 1 or CFG.MechTransparency
  1070.    
  1071.     for _, part in ipairs(fake:GetDescendants()) do
  1072.         if part:IsA("BasePart") then
  1073.             part.Transparency = transparency
  1074.             part.CanCollide = true
  1075.             part.CanQuery = true
  1076.             part.Massless = false
  1077.             part.CanTouch = false
  1078.             pcall(function() part.CollisionGroup = CHAR_GROUP end)
  1079.         end
  1080.     end
  1081.    
  1082.     fake.Name = "NanoMech"
  1083.     fake.Parent = Workspace
  1084.    
  1085.     pcall(function() fake:ScaleTo(CFG.MechScale) end)
  1086.     fake:PivotTo(realChar:GetPivot())
  1087.    
  1088.     local humanoid = fake:FindFirstChildOfClass("Humanoid")
  1089.     if humanoid then
  1090.         humanoid.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
  1091.         humanoid.HealthDisplayType = Enum.HumanoidHealthDisplayType.AlwaysOff
  1092.         humanoid.AutoRotate = true
  1093.         humanoid.WalkSpeed = 16
  1094.         humanoid.JumpPower = 50
  1095.         humanoid.JumpHeight = 7.2
  1096.         humanoid.UseJumpPower = true
  1097.     end
  1098.    
  1099.     return fake, fakeRig
  1100. end
  1101.  
  1102. function NanoCharacter.DisableReal(realChar, CFG, originalStates)
  1103.     if not realChar then return end
  1104.    
  1105.     NanoCharacter.StopAllAnimations(realChar)
  1106.    
  1107.     local realHum = realChar:FindFirstChildOfClass("Humanoid")
  1108.     if realHum then
  1109.         realHum.AutoRotate = false
  1110.         realHum.PlatformStand = true
  1111.         pcall(function() realHum:ChangeState(Enum.HumanoidStateType.Physics) end)
  1112.     end
  1113.    
  1114.     for _, part in ipairs(realChar:GetDescendants()) do
  1115.         if part:IsA("BasePart") then
  1116.             originalStates[part] = {
  1117.                 Transparency = part.Transparency,
  1118.                 CanCollide = part.CanCollide,
  1119.                 CanTouch = part.CanTouch,
  1120.                 CollisionGroup = part.CollisionGroup,
  1121.                 Massless = part.Massless,
  1122.                 CustomPhysicalProperties = part.CustomPhysicalProperties
  1123.             }
  1124.             part.Transparency = CFG.RealCharTransparency
  1125.             part.CanCollide = CFG.RealCharCanCollide
  1126.             part.CanTouch = CFG.RealCharCanTouch
  1127.             part.Massless = true
  1128.             part.CustomPhysicalProperties = PAPER_PHYSICS
  1129.             pcall(function() part.CollisionGroup = CHAR_GROUP end)
  1130.         elseif part:IsA("Decal") then
  1131.             originalStates[part] = {Transparency = part.Transparency}
  1132.             part.Transparency = 1
  1133.         end
  1134.     end
  1135. end
  1136.  
  1137. function NanoCharacter.RestoreReal(realChar, originalStates)
  1138.     if not realChar or not realChar.Parent then return end
  1139.    
  1140.     pcall(function() LocalPlayer.Character = realChar end)
  1141.    
  1142.     for obj, state in pairs(originalStates) do
  1143.         if obj and obj.Parent then
  1144.             pcall(function()
  1145.                 if obj:IsA("BasePart") then
  1146.                     obj.Transparency = state.Transparency or 0
  1147.                     obj.CanCollide = state.CanCollide ~= false
  1148.                     obj.CanTouch = state.CanTouch ~= false
  1149.                     obj.CollisionGroup = state.CollisionGroup or "Default"
  1150.                     obj.Massless = state.Massless or false
  1151.                     if state.CustomPhysicalProperties then
  1152.                         obj.CustomPhysicalProperties = state.CustomPhysicalProperties
  1153.                     end
  1154.                 elseif obj:IsA("Decal") then
  1155.                     obj.Transparency = state.Transparency or 0
  1156.                 end
  1157.             end)
  1158.         end
  1159.     end
  1160.    
  1161.     local realHum = realChar:FindFirstChildOfClass("Humanoid")
  1162.     if realHum then
  1163.         pcall(function()
  1164.             realHum.AutoRotate = true
  1165.             realHum.PlatformStand = false
  1166.             realHum:ChangeState(Enum.HumanoidStateType.GettingUp)
  1167.         end)
  1168.     end
  1169.    
  1170.     NanoCharacter.RestoreAnimations(realChar)
  1171.     pcall(function() Workspace.CurrentCamera.CameraSubject = realHum end)
  1172.     NanoGui.RestoreState()
  1173. end
  1174.  
  1175. function NanoCharacter.SetupAnimations(fakeChar, fakeRig, realRig)
  1176.     if not fakeChar then return end
  1177.    
  1178.     local humanoid = fakeChar:FindFirstChildOfClass("Humanoid")
  1179.     local animate = fakeChar:FindFirstChild("Animate")
  1180.    
  1181.     if humanoid and animate then
  1182.         animate.Disabled = true
  1183.         task.wait(0.15)
  1184.         animate.Disabled = false
  1185.     end
  1186. end
  1187.  
  1188. local function CleanupNano()
  1189.     STARTED = false
  1190.     STARTING = false
  1191.     getgenv().NanoRunning = false
  1192.    
  1193.     for _, connName in ipairs({
  1194.         "NanoConnection", "NanoAttachConnection", "NanoDescendantConnection",
  1195.         "NanoDeathConnection", "NanoCameraConnection", "NanoRenderConnection",
  1196.         "NanoFakeDescendantConnection", "NanoNewPartConnection"
  1197.     }) do
  1198.         if getgenv()[connName] then
  1199.             pcall(function() getgenv()[connName]:Disconnect() end)
  1200.             getgenv()[connName] = nil
  1201.         end
  1202.     end
  1203.    
  1204.     NanoGui.DestroyDebug()
  1205.    
  1206.     if getgenv().NanoRuntime then
  1207.         local Runtime = getgenv().NanoRuntime
  1208.        
  1209.         if Runtime.OriginalFallenPartsHeight then
  1210.             pcall(function() Workspace.FallenPartsDestroyHeight = Runtime.OriginalFallenPartsHeight end)
  1211.         end
  1212.        
  1213.         if Runtime.NoCollisionConstraints then
  1214.             for _, nc in ipairs(Runtime.NoCollisionConstraints) do
  1215.                 pcall(function() nc:Destroy() end)
  1216.             end
  1217.         end
  1218.        
  1219.         for part, data in pairs(Runtime.TrackedParts or {}) do
  1220.             pcall(function()
  1221.                 NanoPhysics.ReturnMovers(data.movers)
  1222.                 part:SetAttribute("NanoLimb", nil)
  1223.                 part:SetAttribute("NanoSlot", nil)
  1224.                 part.CollisionGroup = "Default"
  1225.                 if data.originalProps then
  1226.                     part.CanCollide = data.originalProps.CanCollide
  1227.                     part.Massless = data.originalProps.Massless
  1228.                     part.CanTouch = data.originalProps.CanTouch
  1229.                 end
  1230.             end)
  1231.         end
  1232.        
  1233.         NanoCharacter.RestoreReal(Runtime.RealCharacter, Runtime.OriginalStates)
  1234.        
  1235.         if Runtime.FakeCharacter then
  1236.             pcall(function() Runtime.FakeCharacter:Destroy() end)
  1237.         end
  1238.     end
  1239.    
  1240.     getgenv().NanoRuntime = nil
  1241. end
  1242.  
  1243. CleanupNano()
  1244.  
  1245. local DEFAULT_CONFIGS = {
  1246.     MechScale = 2,
  1247.     MechTransparency = 0.5,
  1248.     MechType = "Full",
  1249.     FakeRig = "R6",
  1250.    
  1251.     R15ExtensionsEnabled = true,
  1252.     R6ExtensionsEnabled = true,
  1253.    
  1254.     RealCharTransparency = 1,
  1255.     RealCharCanCollide = false,
  1256.     RealCharCanTouch = false,
  1257.     RealCharOffset = CFrame.new(0, 0, 0),
  1258.    
  1259.     SimRadius = 1000,
  1260.    
  1261.     SlotPriority = true,
  1262.    
  1263.     CellSize = 0.5,
  1264.    
  1265.     AntisleepEnabled = true,
  1266.     AntisleepVelocity = 0.002,
  1267.    
  1268.     PartsCanCollide = false,
  1269.     PartsMassless = true,
  1270.     DisableTouchInterest = true,
  1271.    
  1272.     PackInterval = 0.1,
  1273.     MaxParts = 512,
  1274.     ChunkSize = 8,
  1275.    
  1276.     ScanMode = "Radius",
  1277.     ScanRadius = 500,
  1278.     ScanFromReal = true,
  1279.     ScanBoxSize = Vector3.new(60, 40, 60),
  1280.     ScanBoxOffset = CFrame.new(0, 0, 0),
  1281.    
  1282.     TransformTimeout = 0.2,
  1283.     DeathRestoreTimeout = 0.5,
  1284.    
  1285.     GroundCheckDistance = 3,
  1286.    
  1287.     JumpDebounce = 0.3,
  1288.    
  1289.     DebugStatsGui = true,
  1290.    
  1291.     MemoryCleanupInterval = 30
  1292. }
  1293.  
  1294. getgenv().NanoConfigs = getgenv().NanoConfigs or {}
  1295. for key, defaultValue in pairs(DEFAULT_CONFIGS) do
  1296.     if getgenv().NanoConfigs[key] == nil then
  1297.         getgenv().NanoConfigs[key] = defaultValue
  1298.     end
  1299. end
  1300.  
  1301. local CFG = getgenv().NanoConfigs
  1302.  
  1303. getgenv().NanoRuntime = {
  1304.     OriginalStates = {},
  1305.     NewPartsTimestamp = {},
  1306.     PendingParts = {},
  1307.     SimRadiusSet = false,
  1308.     FallenPartsSet = false,
  1309.     OriginalFallenPartsHeight = nil,
  1310.     IsRunning = false,
  1311.     IsDead = false,
  1312.     RealCharacter = nil,
  1313.     RealRigType = nil,
  1314.     FakeCharacter = nil,
  1315.     FakeRigType = nil,
  1316.     FakeBodyParts = {},
  1317.     LimbGrids = {},
  1318.     NoCollisionConstraints = {},
  1319.     TrackedParts = {},
  1320.     PartIndex = 0,
  1321.     JumpState = "GROUNDED",
  1322.     IsGrounded = true,
  1323.     LastJumpTime = 0,
  1324.     LastMemoryCleanup = 0,
  1325.     ScannedPartsCount = 0,
  1326.     PendingPartsCount = 0
  1327. }
  1328.  
  1329. local Runtime = getgenv().NanoRuntime
  1330.  
  1331. local function SetSimulationRadius()
  1332.     if Runtime.SimRadiusSet then return end
  1333.     sethidden(LocalPlayer, "SimulationRadius", CFG.SimRadius)
  1334.     sethidden(LocalPlayer, "MaximumSimulationRadius", CFG.SimRadius)
  1335.     Runtime.SimRadiusSet = true
  1336. end
  1337.  
  1338. local function SetFallenPartsDestroyHeight()
  1339.     if Runtime.FallenPartsSet then return end
  1340.     Runtime.OriginalFallenPartsHeight = Workspace.FallenPartsDestroyHeight
  1341.     pcall(function() Workspace.FallenPartsDestroyHeight = -1e9 end)
  1342.     Runtime.FallenPartsSet = true
  1343. end
  1344.  
  1345. local function CleanupOldTimestamps()
  1346.     local now = tick()
  1347.     if now - Runtime.LastMemoryCleanup < CFG.MemoryCleanupInterval then return end
  1348.     Runtime.LastMemoryCleanup = now
  1349.    
  1350.     local toRemove = {}
  1351.     for part, ts in pairs(Runtime.NewPartsTimestamp) do
  1352.         if not part or not part.Parent or (now - ts) > 60 then
  1353.             table.insert(toRemove, part)
  1354.         end
  1355.     end
  1356.     for _, part in ipairs(toRemove) do
  1357.         Runtime.NewPartsTimestamp[part] = nil
  1358.     end
  1359.    
  1360.     NanoPool.CollectFromNil()
  1361. end
  1362.  
  1363. local function SetupCamera()
  1364.     local fakeHum = Runtime.FakeCharacter and Runtime.FakeCharacter:FindFirstChildOfClass("Humanoid")
  1365.     if not fakeHum then return end
  1366.    
  1367.     Workspace.CurrentCamera.CameraType = Enum.CameraType.Custom
  1368.     Workspace.CurrentCamera.CameraSubject = fakeHum
  1369.    
  1370.     if getgenv().NanoCameraConnection then getgenv().NanoCameraConnection:Disconnect() end
  1371.    
  1372.     getgenv().NanoCameraConnection = Workspace.CurrentCamera:GetPropertyChangedSignal("CameraSubject"):Connect(function()
  1373.         if Runtime.IsDead then
  1374.             local targetChar = Runtime.RealCharacter or LocalPlayer.Character
  1375.             if targetChar then
  1376.                 local hum = targetChar:FindFirstChildOfClass("Humanoid")
  1377.                 if hum then Workspace.CurrentCamera.CameraSubject = hum end
  1378.             end
  1379.             return
  1380.         end
  1381.        
  1382.         if not Runtime.IsRunning then return end
  1383.         if Workspace.CurrentCamera.CameraSubject ~= fakeHum then
  1384.             Workspace.CurrentCamera.CameraSubject = fakeHum
  1385.         end
  1386.     end)
  1387. end
  1388.  
  1389. local function SetupNoCollisionConstraints()
  1390.     local realChar = Runtime.RealCharacter
  1391.     local fakeChar = Runtime.FakeCharacter
  1392.     if not realChar or not fakeChar then return end
  1393.    
  1394.     Runtime.NoCollisionConstraints = {}
  1395.    
  1396.     task.spawn(function()
  1397.         local realParts = {}
  1398.         local fakeParts = {}
  1399.        
  1400.         for _, part in ipairs(realChar:GetChildren()) do
  1401.             if part:IsA("BasePart") then
  1402.                 table.insert(realParts, part)
  1403.             end
  1404.         end
  1405.        
  1406.         for _, part in ipairs(fakeChar:GetChildren()) do
  1407.             if part:IsA("BasePart") then
  1408.                 table.insert(fakeParts, part)
  1409.             end
  1410.         end
  1411.        
  1412.         local count = 0
  1413.         for _, realPart in ipairs(realParts) do
  1414.             for _, fakePart in ipairs(fakeParts) do
  1415.                 local nc = Instance.new("NoCollisionConstraint")
  1416.                 nc.Part0 = realPart
  1417.                 nc.Part1 = fakePart
  1418.                 nc.Parent = fakePart
  1419.                 table.insert(Runtime.NoCollisionConstraints, nc)
  1420.                 count = count + 1
  1421.                 if count % 10 == 0 then
  1422.                     task.wait()
  1423.                 end
  1424.             end
  1425.         end
  1426.     end)
  1427. end
  1428.  
  1429. local function SetupFakeCharDescendantTracking()
  1430.     if getgenv().NanoFakeDescendantConnection then getgenv().NanoFakeDescendantConnection:Disconnect() end
  1431.    
  1432.     local fakeChar = Runtime.FakeCharacter
  1433.     if not fakeChar then return end
  1434.    
  1435.     getgenv().NanoFakeDescendantConnection = fakeChar.DescendantAdded:Connect(function(desc)
  1436.         if desc:IsA("BasePart") then
  1437.             pcall(function()
  1438.                 desc.CanTouch = false
  1439.                 desc.CollisionGroup = CHAR_GROUP
  1440.             end)
  1441.         end
  1442.     end)
  1443. end
  1444.  
  1445. local function CreateLimbGrids()
  1446.     local fakeChar = Runtime.FakeCharacter
  1447.     if not fakeChar then return end
  1448.    
  1449.     Runtime.FakeBodyParts = {}
  1450.     Runtime.LimbGrids = {}
  1451.    
  1452.     local partNames = Runtime.FakeRigType == "R15" and LIMB_ORDER_R15 or LIMB_ORDER_R6
  1453.    
  1454.     local effectiveCellSize = CFG.CellSize * CFG.MechScale
  1455.    
  1456.     local extensionConfig = nil
  1457.     if Runtime.FakeRigType == "R15" and CFG.R15ExtensionsEnabled then
  1458.         extensionConfig = {}
  1459.         for limbName, ext in pairs(R15_EXTENSION_CONFIG) do
  1460.             extensionConfig[limbName] = {
  1461.                 sizeAdd = ext.sizeAdd * CFG.MechScale,
  1462.                 offsetY = (ext.offsetY or 0) * CFG.MechScale
  1463.             }
  1464.         end
  1465.     elseif Runtime.FakeRigType == "R6" and CFG.R6ExtensionsEnabled then
  1466.         extensionConfig = {}
  1467.         for limbName, ext in pairs(R6_EXTENSION_CONFIG) do
  1468.             extensionConfig[limbName] = {
  1469.                 sizeAdd = ext.sizeAdd * CFG.MechScale,
  1470.                 offsetY = (ext.offsetY or 0) * CFG.MechScale
  1471.             }
  1472.         end
  1473.     end
  1474.    
  1475.     for _, partName in ipairs(partNames) do
  1476.         if EXCLUDED_PARTS[partName] then continue end
  1477.        
  1478.         local bodyPart = fakeChar:FindFirstChild(partName)
  1479.         if bodyPart and bodyPart:IsA("BasePart") then
  1480.             table.insert(Runtime.FakeBodyParts, bodyPart)
  1481.             Runtime.LimbGrids[partName] = NanoGrid.Create(
  1482.                 bodyPart, effectiveCellSize, CFG.MechType, partName, extensionConfig
  1483.             )
  1484.         end
  1485.     end
  1486. end
  1487.  
  1488. local function SetupAttachConnection()
  1489.     if getgenv().NanoAttachConnection then getgenv().NanoAttachConnection:Disconnect() end
  1490.    
  1491.     getgenv().NanoAttachConnection = RunService.Heartbeat:Connect(function()
  1492.         if not Runtime.IsRunning or Runtime.IsDead then return end
  1493.        
  1494.         local realChar = Runtime.RealCharacter
  1495.         local fakeChar = Runtime.FakeCharacter
  1496.         if not realChar or not realChar.Parent then return end
  1497.         if not fakeChar or not fakeChar.Parent then return end
  1498.        
  1499.         local realHRP = realChar:FindFirstChild("HumanoidRootPart")
  1500.         local fakeHRP = fakeChar:FindFirstChild("HumanoidRootPart")
  1501.         if not realHRP or not fakeHRP then return end
  1502.        
  1503.         local realHum = realChar:FindFirstChildOfClass("Humanoid")
  1504.         if realHum then
  1505.             realHum.PlatformStand = true
  1506.             realHum.AutoRotate = false
  1507.         end
  1508.        
  1509.         realHRP.CFrame = fakeHRP.CFrame * CFG.RealCharOffset
  1510.         realHRP.AssemblyLinearVelocity = fakeHRP.AssemblyLinearVelocity
  1511.         realHRP.AssemblyAngularVelocity = Vector3.zero
  1512.     end)
  1513. end
  1514.  
  1515. local function SetupShiftLockRotation()
  1516.     if getgenv().NanoRenderConnection then getgenv().NanoRenderConnection:Disconnect() end
  1517.    
  1518.     getgenv().NanoRenderConnection = RunService.RenderStepped:Connect(function()
  1519.         if not Runtime.IsRunning or Runtime.IsDead then return end
  1520.        
  1521.         local fakeChar = Runtime.FakeCharacter
  1522.         if not fakeChar then return end
  1523.        
  1524.         local fakeHRP = fakeChar:FindFirstChild("HumanoidRootPart")
  1525.         local fakeHum = fakeChar:FindFirstChildOfClass("Humanoid")
  1526.         if not fakeHRP or not fakeHum then return end
  1527.        
  1528.         local isShiftLock = UserInputService.MouseBehavior == Enum.MouseBehavior.LockCenter
  1529.        
  1530.         if isShiftLock then
  1531.             fakeHum.AutoRotate = false
  1532.             local camCF = Workspace.CurrentCamera.CFrame
  1533.             local _, y, _ = camCF:ToEulerAnglesYXZ()
  1534.             fakeHRP.CFrame = CFrame.new(fakeHRP.Position) * CFrame.Angles(0, y, 0)
  1535.         else
  1536.             fakeHum.AutoRotate = true
  1537.         end
  1538.     end)
  1539. end
  1540.  
  1541. local function CheckGrounded(fakeHRP)
  1542.     local rayParams = RaycastParams.new()
  1543.     rayParams.FilterType = Enum.RaycastFilterType.Exclude
  1544.     rayParams.FilterDescendantsInstances = {Runtime.FakeCharacter, Runtime.RealCharacter}
  1545.    
  1546.     local checkDist = CFG.GroundCheckDistance * CFG.MechScale
  1547.    
  1548.     local offsets = {
  1549.         Vector3.new(0, 0, 0),
  1550.         Vector3.new(1, 0, 0), Vector3.new(-1, 0, 0),
  1551.         Vector3.new(0, 0, 1), Vector3.new(0, 0, -1),
  1552.     }
  1553.    
  1554.     for _, offset in ipairs(offsets) do
  1555.         local origin = fakeHRP.Position + offset * CFG.MechScale * 0.5
  1556.         local result = Workspace:Raycast(origin, Vector3.new(0, -checkDist, 0), rayParams)
  1557.         if result then return true end
  1558.     end
  1559.     return false
  1560. end
  1561.  
  1562. local function SyncMovement()
  1563.     if Runtime.IsDead then return end
  1564.    
  1565.     local fakeChar = Runtime.FakeCharacter
  1566.     local fakeHum = fakeChar and fakeChar:FindFirstChildOfClass("Humanoid")
  1567.     local fakeHRP = fakeChar and fakeChar:FindFirstChild("HumanoidRootPart")
  1568.     if not fakeHum or not fakeHRP then return end
  1569.    
  1570.     Runtime.IsGrounded = CheckGrounded(fakeHRP)
  1571.     local velY = fakeHRP.AssemblyLinearVelocity.Y
  1572.    
  1573.     if Runtime.IsGrounded and math.abs(velY) < 10 then
  1574.         Runtime.JumpState = "GROUNDED"
  1575.     elseif velY > 5 then
  1576.         Runtime.JumpState = "JUMPING"
  1577.     elseif velY < -5 then
  1578.         Runtime.JumpState = "FALLING"
  1579.     end
  1580.    
  1581.     if UserInputService:GetFocusedTextBox() then
  1582.         fakeHum:Move(Vector3.zero, false)
  1583.         return
  1584.     end
  1585.    
  1586.     local camera = Workspace.CurrentCamera
  1587.     local moveDir = Vector3.zero
  1588.    
  1589.     local W = UserInputService:IsKeyDown(Enum.KeyCode.W)
  1590.     local A = UserInputService:IsKeyDown(Enum.KeyCode.A)
  1591.     local S = UserInputService:IsKeyDown(Enum.KeyCode.S)
  1592.     local D = UserInputService:IsKeyDown(Enum.KeyCode.D)
  1593.     local spacePressed = UserInputService:IsKeyDown(Enum.KeyCode.Space)
  1594.    
  1595.     if W or A or S or D then
  1596.         local look = camera.CFrame.LookVector * Vector3.new(1, 0, 1)
  1597.         local right = camera.CFrame.RightVector * Vector3.new(1, 0, 1)
  1598.         if look.Magnitude > 0.01 then look = look.Unit end
  1599.         if right.Magnitude > 0.01 then right = right.Unit end
  1600.        
  1601.         if W then moveDir = moveDir + look end
  1602.         if S then moveDir = moveDir - look end
  1603.         if D then moveDir = moveDir + right end
  1604.         if A then moveDir = moveDir - right end
  1605.        
  1606.         if moveDir.Magnitude > 0.01 then moveDir = moveDir.Unit end
  1607.     end
  1608.    
  1609.     fakeHum:Move(moveDir, false)
  1610.    
  1611.     local now = tick()
  1612.     if spacePressed and Runtime.IsGrounded and (now - Runtime.LastJumpTime) > CFG.JumpDebounce then
  1613.         Runtime.LastJumpTime = now
  1614.         fakeHum.Jump = true
  1615.     end
  1616. end
  1617.  
  1618. local function IsValidPart(part)
  1619.     if part.Anchored then return false end
  1620.     if part:IsA("Terrain") then return false end
  1621.     if string.find(part.Name, "Nano") then return false end
  1622.     if Runtime.RealCharacter and part:IsDescendantOf(Runtime.RealCharacter) then return false end
  1623.     if Runtime.FakeCharacter and part:IsDescendantOf(Runtime.FakeCharacter) then return false end
  1624.    
  1625.     local ancestor = part.Parent
  1626.     while ancestor and ancestor ~= Workspace do
  1627.         if ancestor:FindFirstChildOfClass("Humanoid") then return false end
  1628.         ancestor = ancestor.Parent
  1629.     end
  1630.    
  1631.     local ts = Runtime.NewPartsTimestamp[part]
  1632.     if ts and tick() - ts < CFG.TransformTimeout then return false end
  1633.    
  1634.     if part.Size.X * part.Size.Y * part.Size.Z < 0.001 then return false end
  1635.    
  1636.     local maxSize = 10 * CFG.MechScale
  1637.     if part.Size.X > maxSize or part.Size.Y > maxSize or part.Size.Z > maxSize then
  1638.         return false
  1639.     end
  1640.    
  1641.     return true
  1642. end
  1643.  
  1644. local function SetupNewPartDetection()
  1645.     if getgenv().NanoNewPartConnection then getgenv().NanoNewPartConnection:Disconnect() end
  1646.    
  1647.     getgenv().NanoNewPartConnection = Workspace.DescendantAdded:Connect(function(desc)
  1648.         if not Runtime.IsRunning or Runtime.IsDead then return end
  1649.        
  1650.         if desc:IsA("BasePart") then
  1651.             Runtime.NewPartsTimestamp[desc] = tick()
  1652.            
  1653.             task.delay(CFG.TransformTimeout + 0.05, function()
  1654.                 if not Runtime.IsRunning or Runtime.IsDead then return end
  1655.                 if desc and desc.Parent and IsValidPart(desc) and not Runtime.TrackedParts[desc] then
  1656.                     Runtime.PendingParts[desc] = true
  1657.                 end
  1658.             end)
  1659.         end
  1660.     end)
  1661. end
  1662.  
  1663. local function ScanParts()
  1664.     local scanPos
  1665.    
  1666.     if CFG.ScanFromReal and Runtime.RealCharacter then
  1667.         local realHRP = Runtime.RealCharacter:FindFirstChild("HumanoidRootPart")
  1668.         if realHRP then scanPos = realHRP.Position end
  1669.     end
  1670.    
  1671.     if not scanPos and Runtime.FakeCharacter then
  1672.         local fakeHRP = Runtime.FakeCharacter:FindFirstChild("HumanoidRootPart")
  1673.         if fakeHRP then scanPos = fakeHRP.Position end
  1674.     end
  1675.    
  1676.     if not scanPos then return {} end
  1677.    
  1678.     local params = OverlapParams.new()
  1679.     params.FilterType = Enum.RaycastFilterType.Exclude
  1680.    
  1681.     local filterList = {}
  1682.     for _, player in ipairs(Players:GetPlayers()) do
  1683.         if player.Character then table.insert(filterList, player.Character) end
  1684.     end
  1685.     if Runtime.RealCharacter then table.insert(filterList, Runtime.RealCharacter) end
  1686.     if Runtime.FakeCharacter then table.insert(filterList, Runtime.FakeCharacter) end
  1687.     params.FilterDescendantsInstances = filterList
  1688.     params.MaxParts = CFG.MaxParts * 2
  1689.    
  1690.     local raw
  1691.     if CFG.ScanMode == "Box" then
  1692.         raw = Workspace:GetPartBoundsInBox(CFrame.new(scanPos) * CFG.ScanBoxOffset, CFG.ScanBoxSize, params)
  1693.     else
  1694.         raw = Workspace:GetPartBoundsInRadius(scanPos, CFG.ScanRadius, params)
  1695.     end
  1696.    
  1697.     local valid = {}
  1698.     for _, part in ipairs(raw) do
  1699.         if #valid >= CFG.MaxParts then break end
  1700.         if part:IsA("BasePart") and part.Parent and IsValidPart(part) then
  1701.             table.insert(valid, part)
  1702.         end
  1703.     end
  1704.    
  1705.     for part in pairs(Runtime.PendingParts) do
  1706.         if part and part.Parent and IsValidPart(part) and not Runtime.TrackedParts[part] then
  1707.             if #valid < CFG.MaxParts then
  1708.                 table.insert(valid, part)
  1709.             end
  1710.         end
  1711.         Runtime.PendingParts[part] = nil
  1712.     end
  1713.    
  1714.     Runtime.ScannedPartsCount = #valid
  1715.     Runtime.PendingPartsCount = 0
  1716.     for _ in pairs(Runtime.PendingParts) do
  1717.         Runtime.PendingPartsCount = Runtime.PendingPartsCount + 1
  1718.     end
  1719.    
  1720.     table.sort(valid, function(a, b)
  1721.         return a.Size.X * a.Size.Y * a.Size.Z > b.Size.X * b.Size.Y * b.Size.Z
  1722.     end)
  1723.    
  1724.     return valid
  1725. end
  1726.  
  1727. local function FindBestLimbForPart(part)
  1728.     local existingLimb = part:GetAttribute("NanoLimb")
  1729.     if existingLimb and Runtime.LimbGrids[existingLimb] then return existingLimb end
  1730.    
  1731.     local partSize = part.Size
  1732.     local closest = nil
  1733.     local closestScore = -math.huge
  1734.    
  1735.     for name, grid in pairs(Runtime.LimbGrids) do
  1736.         if EXCLUDED_PARTS[name] then continue end
  1737.         if grid.bodyPart and grid.bodyPart.Parent then
  1738.             local gridPos, rotData, cells, score = NanoGrid.FindBestPlacement(grid, partSize, CFG.SlotPriority)
  1739.             if gridPos and score > closestScore then
  1740.                 closestScore = score
  1741.                 closest = name
  1742.             end
  1743.         end
  1744.     end
  1745.    
  1746.     return closest
  1747. end
  1748.  
  1749. local function AttachPartToGrid(part, grid)
  1750.     local partSize = part.Size
  1751.     local gridPos, rotData, cells, score = NanoGrid.FindBestPlacement(grid, partSize, CFG.SlotPriority)
  1752.     if not gridPos then return false end
  1753.    
  1754.     local limbName = grid.bodyPart.Name
  1755.    
  1756.     if EXCLUDED_PARTS[limbName] then return false end
  1757.    
  1758.     local hasTouchInterest = NanoCharacter.HasTouchInterest(part)
  1759.    
  1760.     local originalProps = {
  1761.         CanCollide = part.CanCollide,
  1762.         Massless = part.Massless,
  1763.         CollisionGroup = part.CollisionGroup,
  1764.         CanTouch = part.CanTouch
  1765.     }
  1766.    
  1767.     pcall(function()
  1768.         part.CollisionGroup = NANO_GROUP
  1769.         part.CanCollide = CFG.PartsCanCollide
  1770.         part.Massless = CFG.PartsMassless
  1771.         if CFG.DisableTouchInterest or hasTouchInterest then
  1772.             part.CanTouch = false
  1773.         end
  1774.     end)
  1775.    
  1776.     NanoGrid.MarkAreaOccupied(grid, gridPos.X, gridPos.Y, gridPos.Z, cells.X, cells.Y, cells.Z, part)
  1777.    
  1778.     local worldOffset = NanoGrid.GetWorldOffset(grid, gridPos, cells)
  1779.     local rotation = rotData.cf
  1780.     local movers = NanoPhysics.CreateAlignMovers(part, grid.bodyPart, worldOffset, rotation)
  1781.    
  1782.     Runtime.PartIndex = Runtime.PartIndex + 1
  1783.     part:SetAttribute("NanoLimb", limbName)
  1784.     part:SetAttribute("NanoSlot", Runtime.PartIndex)
  1785.    
  1786.     Runtime.TrackedParts[part] = {
  1787.         limbName = limbName,
  1788.         grid = grid,
  1789.         gridPos = gridPos,
  1790.         cells = cells,
  1791.         rotation = rotation,
  1792.         worldOffset = worldOffset,
  1793.         movers = movers,
  1794.         originalProps = originalProps,
  1795.         index = Runtime.PartIndex
  1796.     }
  1797.    
  1798.     return true
  1799. end
  1800.  
  1801. local function DetachPart(part)
  1802.     local data = Runtime.TrackedParts[part]
  1803.     if not data then return end
  1804.    
  1805.     NanoPhysics.ReturnMovers(data.movers)
  1806.    
  1807.     if data.grid and data.gridPos and data.cells then
  1808.         NanoGrid.MarkAreaFree(data.grid, data.gridPos.X, data.gridPos.Y, data.gridPos.Z, data.cells.X, data.cells.Y, data.cells.Z)
  1809.     end
  1810.    
  1811.     if data.originalProps and part and part.Parent then
  1812.         pcall(function()
  1813.             part.CanCollide = data.originalProps.CanCollide
  1814.             part.Massless = data.originalProps.Massless
  1815.             part.CollisionGroup = data.originalProps.CollisionGroup or "Default"
  1816.             part.CanTouch = data.originalProps.CanTouch
  1817.         end)
  1818.     end
  1819.    
  1820.     pcall(function()
  1821.         part:SetAttribute("NanoLimb", nil)
  1822.         part:SetAttribute("NanoSlot", nil)
  1823.     end)
  1824.    
  1825.     Runtime.TrackedParts[part] = nil
  1826. end
  1827.  
  1828. local function ProcessPartsChunked(parts)
  1829.     local currentParts = {}
  1830.     for _, p in ipairs(parts) do currentParts[p] = true end
  1831.    
  1832.     local toRemove = {}
  1833.     for part in pairs(Runtime.TrackedParts) do
  1834.         if not currentParts[part] or not part.Parent then
  1835.             table.insert(toRemove, part)
  1836.         end
  1837.     end
  1838.     for _, part in ipairs(toRemove) do DetachPart(part) end
  1839.    
  1840.     local toAttach = {}
  1841.     for _, part in ipairs(parts) do
  1842.         if not Runtime.TrackedParts[part] then
  1843.             table.insert(toAttach, part)
  1844.         end
  1845.     end
  1846.    
  1847.     if #toAttach == 0 then return end
  1848.    
  1849.     local chunkSize = CFG.ChunkSize
  1850.     local processed = 0
  1851.    
  1852.     local function processChunk()
  1853.         if Runtime.IsDead or not Runtime.IsRunning then return end
  1854.        
  1855.         local startIdx = processed + 1
  1856.         local endIdx = math.min(processed + chunkSize, #toAttach)
  1857.        
  1858.         for i = startIdx, endIdx do
  1859.             local part = toAttach[i]
  1860.             if part and part.Parent and not Runtime.TrackedParts[part] then
  1861.                 local limbName = FindBestLimbForPart(part)
  1862.                 if limbName and not EXCLUDED_PARTS[limbName] then
  1863.                     local grid = Runtime.LimbGrids[limbName]
  1864.                     if grid then AttachPartToGrid(part, grid) end
  1865.                 end
  1866.             end
  1867.         end
  1868.        
  1869.         processed = endIdx
  1870.         if processed < #toAttach then task.defer(processChunk) end
  1871.     end
  1872.    
  1873.     task.spawn(processChunk)
  1874. end
  1875.  
  1876. local function UpdateMovers()
  1877.     if Runtime.IsDead then return end
  1878.    
  1879.     local toRemove = {}
  1880.     for part, data in pairs(Runtime.TrackedParts) do
  1881.         if not part or not part.Parent then
  1882.             table.insert(toRemove, part)
  1883.         elseif not data.grid or not data.grid.bodyPart or not data.grid.bodyPart.Parent then
  1884.             table.insert(toRemove, part)
  1885.         else
  1886.             NanoPhysics.ApplyAntisleep(part, CFG, LocalPlayer)
  1887.         end
  1888.     end
  1889.    
  1890.     for _, part in ipairs(toRemove) do DetachPart(part) end
  1891.     pcall(function() settings().Physics.AllowSleep = false end)
  1892. end
  1893.  
  1894. local function OnDeath()
  1895.     if Runtime.IsDead then return end
  1896.     Runtime.IsDead = true
  1897.     Runtime.IsRunning = false
  1898.    
  1899.     if Runtime.FakeCharacter then
  1900.         local fakeHum = Runtime.FakeCharacter:FindFirstChildOfClass("Humanoid")
  1901.         if fakeHum then
  1902.             pcall(function()
  1903.                 fakeHum.WalkSpeed = 0
  1904.                 fakeHum.JumpPower = 0
  1905.                 fakeHum.PlatformStand = true
  1906.             end)
  1907.         end
  1908.     end
  1909.    
  1910.     local camera = Workspace.CurrentCamera
  1911.     camera.CameraType = Enum.CameraType.Custom
  1912.    
  1913.     local targetChar = Runtime.RealCharacter or LocalPlayer.Character
  1914.     if targetChar then
  1915.         local hum = targetChar:FindFirstChildOfClass("Humanoid")
  1916.         if hum then camera.CameraSubject = hum end
  1917.     end
  1918.    
  1919.     for part in pairs(Runtime.TrackedParts) do DetachPart(part) end
  1920.     task.delay(CFG.DeathRestoreTimeout, CleanupNano)
  1921. end
  1922.  
  1923. local function SetupDeathDetection()
  1924.     if getgenv().NanoDeathConnection then getgenv().NanoDeathConnection:Disconnect() end
  1925.    
  1926.     local fakeChar = Runtime.FakeCharacter
  1927.     local realChar = Runtime.RealCharacter
  1928.    
  1929.     if fakeChar then
  1930.         local hum = fakeChar:FindFirstChildOfClass("Humanoid")
  1931.         if hum then hum.Died:Once(OnDeath) end
  1932.     end
  1933.    
  1934.     if realChar then
  1935.         local hum = realChar:FindFirstChildOfClass("Humanoid")
  1936.         if hum then hum.Died:Once(OnDeath) end
  1937.     end
  1938.    
  1939.     getgenv().NanoDeathConnection = RunService.Heartbeat:Connect(function()
  1940.         if Runtime.IsDead then return end
  1941.         if not Runtime.FakeCharacter or not Runtime.FakeCharacter.Parent then OnDeath()
  1942.         elseif not Runtime.RealCharacter or not Runtime.RealCharacter.Parent then OnDeath() end
  1943.     end)
  1944. end
  1945.  
  1946. local function StartNano()
  1947.     if STARTING or STARTED then return end
  1948.     STARTING = true
  1949.    
  1950.     local char = LocalPlayer.Character
  1951.     if not char then STARTING = false return end
  1952.    
  1953.     local root = char:FindFirstChild("HumanoidRootPart")
  1954.     local hum = char:FindFirstChildOfClass("Humanoid")
  1955.     if not root or not hum then STARTING = false return end
  1956.    
  1957.     NanoPool.Init()
  1958.     NanoGui.SaveState()
  1959.    
  1960.     Runtime.RealCharacter = char
  1961.     Runtime.RealRigType = NanoCharacter.GetRigType(char)
  1962.     Runtime.IsDead = false
  1963.     Runtime.LastJumpTime = 0
  1964.    
  1965.     local fake, fakeRig = NanoCharacter.CreateFake(char, CFG.FakeRig, CFG)
  1966.     if not fake then
  1967.         warn("[NANO] Failed to create fake")
  1968.         STARTING = false
  1969.         return
  1970.     end
  1971.    
  1972.     Runtime.FakeCharacter = fake
  1973.     Runtime.FakeRigType = fakeRig
  1974.    
  1975.     local fakeHRP = fake:FindFirstChild("HumanoidRootPart")
  1976.     if not fakeHRP then
  1977.         fake:Destroy()
  1978.         STARTING = false
  1979.         return
  1980.     end
  1981.    
  1982.     SetupNoCollisionConstraints()
  1983.     NanoCharacter.DisableReal(char, CFG, Runtime.OriginalStates)
  1984.     NanoCharacter.DisableTouchOnCharacter(fake)
  1985.     SetupFakeCharDescendantTracking()
  1986.     CreateLimbGrids()
  1987.    
  1988.     LocalPlayer.Character = fake
  1989.    
  1990.     task.wait(0.1)
  1991.     NanoGui.RestoreState()
  1992.    
  1993.     SetupCamera()
  1994.     SetupAttachConnection()
  1995.     SetupShiftLockRotation()
  1996.    
  1997.     task.wait(0.2)
  1998.     NanoCharacter.SetupAnimations(fake, fakeRig, Runtime.RealRigType)
  1999.    
  2000.     Runtime.IsRunning = true
  2001.     STARTED = true
  2002.     STARTING = false
  2003.    
  2004.     SetSimulationRadius()
  2005.     SetFallenPartsDestroyHeight()
  2006.     SetupDeathDetection()
  2007.     SetupNewPartDetection()
  2008.    
  2009.     if CFG.DebugStatsGui then NanoGui.CreateDebug(Runtime, CFG) end
  2010.    
  2011.     local lastPackTime = 0
  2012.    
  2013.     getgenv().NanoConnection = RunService.Heartbeat:Connect(function()
  2014.         if not Runtime.IsRunning or Runtime.IsDead then return end
  2015.        
  2016.         local fakeChar = Runtime.FakeCharacter
  2017.         if not fakeChar or not fakeChar.Parent then return end
  2018.        
  2019.         SyncMovement()
  2020.         UpdateMovers()
  2021.         CleanupOldTimestamps()
  2022.        
  2023.         if CFG.DebugStatsGui then NanoGui.UpdateDebug(Runtime, CFG) end
  2024.        
  2025.         local now = tick()
  2026.         if now - lastPackTime >= CFG.PackInterval then
  2027.             lastPackTime = now
  2028.             local parts = ScanParts()
  2029.             ProcessPartsChunked(parts)
  2030.         end
  2031.     end)
  2032.    
  2033.     StarterGui:SetCore("SendNotification", {
  2034.         Title = "NanoMech v3.6",
  2035.         Text = string.format("%s→%s | Scale:%.1fx | %s",
  2036.             Runtime.RealRigType, Runtime.FakeRigType, CFG.MechScale, CFG.MechType),
  2037.         Duration = 3
  2038.     })
  2039. end
  2040.  
  2041. getgenv().NanoAPI = {
  2042.     Start = StartNano,
  2043.     Stop = CleanupNano,
  2044.    
  2045.     SetScale = function(scale)
  2046.         CFG.MechScale = scale
  2047.         if Runtime.FakeCharacter then
  2048.             pcall(function() Runtime.FakeCharacter:ScaleTo(scale) end)
  2049.             for part in pairs(Runtime.TrackedParts) do DetachPart(part) end
  2050.             CreateLimbGrids()
  2051.         end
  2052.     end,
  2053.    
  2054.     SetMechType = function(mechType)
  2055.         CFG.MechType = mechType
  2056.         for part in pairs(Runtime.TrackedParts) do DetachPart(part) end
  2057.         CreateLimbGrids()
  2058.     end,
  2059.    
  2060.     SetFakeRig = function(rig) CFG.FakeRig = NanoCharacter.NormalizeRig(rig) end,
  2061.    
  2062.     SetCellSize = function(size)
  2063.         CFG.CellSize = size
  2064.         for part in pairs(Runtime.TrackedParts) do DetachPart(part) end
  2065.         CreateLimbGrids()
  2066.     end,
  2067.    
  2068.     SetDebugGui = function(enabled)
  2069.         CFG.DebugStatsGui = enabled
  2070.         if enabled then NanoGui.CreateDebug(Runtime, CFG) else NanoGui.DestroyDebug() end
  2071.     end,
  2072.    
  2073.     ToggleR15Extensions = function(enabled)
  2074.         CFG.R15ExtensionsEnabled = enabled
  2075.         for part in pairs(Runtime.TrackedParts) do DetachPart(part) end
  2076.         CreateLimbGrids()
  2077.     end,
  2078.    
  2079.     ToggleR6Extensions = function(enabled)
  2080.         CFG.R6ExtensionsEnabled = enabled
  2081.         for part in pairs(Runtime.TrackedParts) do DetachPart(part) end
  2082.         CreateLimbGrids()
  2083.     end,
  2084.    
  2085.     SetChunkSize = function(size) CFG.ChunkSize = size end,
  2086.     SetScanRadius = function(radius) CFG.ScanRadius = radius end,
  2087.     SetJumpDebounce = function(time) CFG.JumpDebounce = time end,
  2088.    
  2089.     GetPoolStats = function() return NanoPool.Stats end,
  2090.     GetRuntime = function() return Runtime end,
  2091.     GetConfig = function() return CFG end,
  2092.    
  2093.     ForceRefreshGrids = function()
  2094.         for part in pairs(Runtime.TrackedParts) do DetachPart(part) end
  2095.         CreateLimbGrids()
  2096.     end,
  2097.    
  2098.     CopyDebugInfo = function()
  2099.         NanoGui.CopyInfo(Runtime, CFG)
  2100.     end
  2101. }
  2102.  
  2103. task.wait(0.5)
  2104. StartNano()
Advertisement
Add Comment
Please, Sign In to add comment