Josiahiscool73

animation stealer

Feb 19th, 2026
65
0
Never
6
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 44.29 KB | None | 0 0
  1. -- steal anims
  2. local Players = game:GetService("Players")
  3. local RunService = game:GetService("RunService")
  4. local UserInputService = game:GetService("UserInputService")
  5. local HttpService = game:GetService("HttpService")
  6. local Workspace = game:GetService("Workspace")
  7. local StarterGui = game:GetService("StarterGui")
  8. local Selection = game:GetService("Selection")
  9.  
  10. local player = Players.LocalPlayer
  11. local character = player.Character or player.CharacterAdded:Wait()
  12. local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
  13.  
  14. local CLONE_DISTANCE = 5
  15. local FOLDER_NAME = "StolenAnims"
  16. local MAX_CHUNK_SIZE = 190000
  17.  
  18. -- Two separate clones running in parallel
  19. local myCloneR6, myCloneR15 = nil, nil
  20. -- Rest-pose world CFrames captured when the R15 clone spawns; used by R6->R15 converter
  21. local r15RestPose = {}
  22. local r15RestHRPCF = CFrame.identity
  23.  
  24. local isRecording, recordingType = false, "Player"
  25. local recordedFrames, recordedFramesBoth_Player, recordedFramesBoth_Model = {}, {}, {}
  26. local recordConnection, replayConnection, isReplaying = nil, nil, false
  27. local playerBodyParts, modelBodyParts = {}, {}
  28. local dragging, dragInput, dragStart, startPos = false, nil, nil, nil
  29. local selectedModel, originalMotorStates = nil, {}
  30. local sourceAnimType = "R6"
  31. local playerAnimType = "R6"
  32. local modelAnimType = "R6"
  33. local recordTimestamps, recordTimestamps_Player, recordTimestamps_Model = {}, {}, {}
  34.  
  35. local bodyPartNames = {
  36. "Head","HumanoidRootPart","Left Arm","Left Leg","Right Arm","Right Leg","Torso",
  37. "UpperTorso","LowerTorso","LeftUpperArm","LeftLowerArm","LeftHand",
  38. "RightUpperArm","RightLowerArm","RightHand","LeftUpperLeg","LeftLowerLeg",
  39. "LeftFoot","RightUpperLeg","RightLowerLeg","RightFoot"
  40. }
  41.  
  42. local r6PartNames = {
  43. "Head","HumanoidRootPart","Left Arm","Left Leg","Right Arm","Right Leg","Torso"
  44. }
  45.  
  46. local r15PartNames = {
  47. "HumanoidRootPart","Head",
  48. "UpperTorso","LowerTorso",
  49. "LeftUpperArm","LeftLowerArm","LeftHand",
  50. "RightUpperArm","RightLowerArm","RightHand",
  51. "LeftUpperLeg","LeftLowerLeg","LeftFoot",
  52. "RightUpperLeg","RightLowerLeg","RightFoot"
  53. }
  54.  
  55. -- Any body part name (R6 or R15) → the R6 equivalent
  56. -- Used for accessory attachment resolution on the R6 dummy
  57. local r15ToR6PartName = {
  58. ["HumanoidRootPart"]="HumanoidRootPart",["Head"]="Head",
  59. ["Torso"]="Torso",["Left Arm"]="Left Arm",["Right Arm"]="Right Arm",
  60. ["Left Leg"]="Left Leg",["Right Leg"]="Right Leg",
  61. ["UpperTorso"]="Torso",["LowerTorso"]="Torso",
  62. ["LeftUpperArm"]="Left Arm",["LeftLowerArm"]="Left Arm",["LeftHand"]="Left Arm",
  63. ["RightUpperArm"]="Right Arm",["RightLowerArm"]="Right Arm",["RightHand"]="Right Arm",
  64. ["LeftUpperLeg"]="Left Leg",["LeftLowerLeg"]="Left Leg",["LeftFoot"]="Left Leg",
  65. ["RightUpperLeg"]="Right Leg",["RightLowerLeg"]="Right Leg",["RightFoot"]="Right Leg",
  66. }
  67.  
  68. -- ─────────────────────────────────────────────────────────────────────────────
  69. -- ROTATION UTILITIES
  70. -- ─────────────────────────────────────────────────────────────────────────────
  71.  
  72. local function getPureRotation(cf)
  73. return CFrame.fromMatrix(Vector3.zero, cf.RightVector, cf.UpVector, -cf.LookVector)
  74. end
  75.  
  76. local function blendRotations(cframes, weights)
  77. if #cframes == 0 then return CFrame.identity end
  78. if #cframes == 1 then return getPureRotation(cframes[1]) end
  79. local result, accW = getPureRotation(cframes[1]), weights[1]
  80. for i = 2, #cframes do
  81. accW = accW + weights[i]
  82. result = result:Lerp(getPureRotation(cframes[i]), weights[i] / accW)
  83. end
  84. return result
  85. end
  86.  
  87. -- ─────────────────────────────────────────────────────────────────────────────
  88. -- R15 → R6 CONVERSION
  89. -- ─────────────────────────────────────────────────────────────────────────────
  90.  
  91. local function convertR15ToR6Frame(r15Frame)
  92. local r6Frame = {}
  93. local function getCF(n) local e = r15Frame[n]; return e and e.CFrame or nil end
  94.  
  95. local hrp = getCF("HumanoidRootPart")
  96. if hrp then r6Frame["HumanoidRootPart"] = { CFrame = hrp } end
  97.  
  98. local ut, lt = getCF("UpperTorso"), getCF("LowerTorso")
  99. if ut then
  100. r6Frame["Torso"] = { CFrame = getPureRotation(ut) + (lt and (ut.Position*0.55 + lt.Position*0.45) or ut.Position) }
  101. elseif lt then r6Frame["Torso"] = { CFrame = lt } end
  102.  
  103. local head = getCF("Head")
  104. if head then r6Frame["Head"] = { CFrame = head } end
  105.  
  106. local function limb(uN,lN,eN,r6N,uw,lw)
  107. local u = getCF(uN); if not u then return end
  108. local l, e = getCF(lN), getCF(eN)
  109. local rot = l and blendRotations({u,l},{uw,lw}) or getPureRotation(u)
  110. local bot = e and e.Position or (l and l.Position or u.Position)
  111. r6Frame[r6N] = { CFrame = rot + u.Position:Lerp(bot, 0.5) }
  112. end
  113.  
  114. limb("LeftUpperArm","LeftLowerArm","LeftHand","Left Arm",0.65,0.35)
  115. limb("RightUpperArm","RightLowerArm","RightHand","Right Arm",0.65,0.35)
  116. limb("LeftUpperLeg","LeftLowerLeg","LeftFoot","Left Leg",0.55,0.45)
  117. limb("RightUpperLeg","RightLowerLeg","RightFoot","Right Leg",0.55,0.45)
  118.  
  119. return r6Frame
  120. end
  121.  
  122. -- ─────────────────────────────────────────────────────────────────────────────
  123. -- R6 → R15 CONVERSION (new)
  124. -- ─────────────────────────────────────────────────────────────────────────────
  125. --[[
  126. For each R15 part:
  127. Position → its rest-pose local offset from the rest HRP, re-applied under
  128. the animated HRP. This keeps UpperArm / LowerArm / Hand spaced
  129. along the limb correctly as the arm swings.
  130. Rotation → the rotation of the corresponding R6 limb relative to the HRP.
  131. All sub-segments of the same R6 limb share this rotation (R6 has
  132. no per-sub-segment twist, so this is the most faithful mapping).
  133.  
  134. restPose : { partName = worldCFrame } captured at R15 clone spawn.
  135. restHRPCF : world CFrame of the R15 clone HRP at spawn.
  136. ]]
  137. local function convertR6ToR15Frame(r6Frame, restPose, restHRPCF)
  138. local r15Frame = {}
  139. local function r6CF(n) local e = r6Frame[n]; return e and e.CFrame or nil end
  140.  
  141. local animHRP = r6CF("HumanoidRootPart")
  142. if not animHRP then return r15Frame end
  143.  
  144. local restHRPInv = restHRPCF:Inverse()
  145.  
  146. for _, partName in ipairs(r15PartNames) do
  147. local restWorld = restPose[partName]
  148. if not restWorld then continue end
  149.  
  150. local r6Name = r15ToR6PartName[partName]
  151. local srcCF = r6CF(r6Name)
  152.  
  153. -- Rest-pose position in HRP-local space
  154. local restLocalPos = (restHRPInv * restWorld).Position
  155.  
  156. -- Local rotation from R6 source (relative to animated HRP)
  157. local localRot
  158. if srcCF then
  159. localRot = getPureRotation(animHRP:Inverse() * srcCF)
  160. else
  161. -- Fallback: keep rest-pose local orientation
  162. localRot = getPureRotation(restHRPInv * restWorld)
  163. end
  164.  
  165. -- World CFrame = animated HRP position/orientation * rest-local offset * r6 rotation
  166. r15Frame[partName] = { CFrame = animHRP * CFrame.new(restLocalPos) * localRot }
  167. end
  168.  
  169. return r15Frame
  170. end
  171.  
  172. -- ─────────────────────────────────────────────────────────────────────────────
  173. -- TEMPORAL RESAMPLING
  174. -- ─────────────────────────────────────────────────────────────────────────────
  175.  
  176. local function resampleFrames(frames, partNames, targetFPS, recordedFPS)
  177. if math.abs(targetFPS - recordedFPS) < 1 then return frames end
  178. local ratio = recordedFPS / targetFPS
  179. local count = math.max(1, math.floor(#frames * targetFPS / recordedFPS))
  180. local result = {}
  181. for i = 1, count do
  182. local srcIdx = (i-1)*ratio + 1
  183. local lo = math.max(1, math.floor(srcIdx))
  184. local hi = math.min(#frames, lo+1)
  185. local alpha = srcIdx - lo
  186. if lo == hi or alpha < 0.001 then
  187. result[i] = frames[lo]
  188. else
  189. local fa, fb, blended = frames[lo], frames[hi], {}
  190. for _, pn in ipairs(partNames) do
  191. local a, b = fa[pn], fb[pn]
  192. if a and b then blended[pn] = { CFrame = a.CFrame:Lerp(b.CFrame, alpha) }
  193. elseif a then blended[pn] = a end
  194. end
  195. result[i] = blended
  196. end
  197. end
  198. return result
  199. end
  200.  
  201. local function prepareForR6(frames, sourceType, targetFPS, recFPS)
  202. local converted = frames
  203. if sourceType == "R15" then
  204. converted = {}
  205. for i, f in ipairs(frames) do converted[i] = convertR15ToR6Frame(f) end
  206. end
  207. return resampleFrames(converted, r6PartNames, targetFPS or 60, recFPS or 60)
  208. end
  209.  
  210. local function prepareForR15(frames, sourceType, targetFPS, recFPS)
  211. local converted = frames
  212. if sourceType == "R6" then
  213. converted = {}
  214. for i, f in ipairs(frames) do
  215. converted[i] = convertR6ToR15Frame(f, r15RestPose, r15RestHRPCF)
  216. end
  217. end
  218. return resampleFrames(converted, r15PartNames, targetFPS or 60, recFPS or 60)
  219. end
  220.  
  221. -- ─────────────────────────────────────────────────────────────────────────────
  222. -- UTILITIES
  223. -- ─────────────────────────────────────────────────────────────────────────────
  224.  
  225. local function detectModelType(model)
  226. if not model then return "Unknown" end
  227. if model:FindFirstChild("UpperTorso", true) then return "R15" end
  228. if model:FindFirstChild("Torso", true) then return "R6" end
  229. return "Unknown"
  230. end
  231.  
  232. local function estimateFPS(ts)
  233. if #ts < 2 then return 60 end
  234. return (#ts-1) / math.max(ts[#ts] - ts[1], 0.001)
  235. end
  236.  
  237. -- ─────────────────────────────────────────────────────────────────────────────
  238. -- FILESYSTEM
  239. -- ─────────────────────────────────────────────────────────────────────────────
  240.  
  241. local HasFileSystem = (getgenv and (writefile or getgenv().writefile)) ~= nil
  242. local IS_STUDIO = not HasFileSystem
  243. local FileSystem = {}
  244.  
  245. if IS_STUDIO then
  246. local OutputFolder = Workspace:FindFirstChild("Stolen_Anims_Output")
  247. if not OutputFolder then
  248. OutputFolder = Instance.new("Folder")
  249. OutputFolder.Name = "Stolen_Anims_Output"
  250. OutputFolder.Parent = Workspace
  251. end
  252. FileSystem.Enabled = true
  253. FileSystem.IsFolder = function() return true end
  254. FileSystem.MakeFolder = function() end
  255. FileSystem.List = function()
  256. local files, seen = {}, {}
  257. for _, child in ipairs(OutputFolder:GetChildren()) do
  258. if child:IsA("ModuleScript") then
  259. local base = child.Name:match("(.+)_Part%d+$") or child.Name
  260. if not seen[base] then seen[base]=true; table.insert(files, FOLDER_NAME.."/"..base..".json") end
  261. end
  262. end
  263. return files
  264. end
  265. FileSystem.Write = function(path, data)
  266. local filename = path:match("([^/]+)%.json$") or "Unknown"
  267. for _, child in ipairs(OutputFolder:GetChildren()) do
  268. if child:IsA("ModuleScript") and (child.Name==filename or child.Name:match("^"..filename.."_Part%d+$")) then child:Destroy() end
  269. end
  270. local safe = data:gsub("\\","\\\\"):gsub("]]","\\]\\]")
  271. if #safe > MAX_CHUNK_SIZE then
  272. for i = 1, math.ceil(#safe/MAX_CHUNK_SIZE) do
  273. local chunk = safe:sub((i-1)*MAX_CHUNK_SIZE+1, math.min(i*MAX_CHUNK_SIZE,#safe))
  274. local m = Instance.new("ModuleScript"); m.Name=filename.."_Part"..i; m.Parent=OutputFolder; m.Source="return [[\n"..chunk.."\n]]"
  275. end
  276. else
  277. local m = Instance.new("ModuleScript"); m.Name=filename; m.Parent=OutputFolder; m.Source="return [[\n"..safe.."\n]]"
  278. end
  279. end
  280. FileSystem.Read = function(path)
  281. local filename = path:match("([^/]+)%.json$")
  282. local parts = {}
  283. for i = 1, 100 do
  284. local m = OutputFolder:FindFirstChild(filename.."_Part"..i)
  285. if m then local fn=loadstring(m.Source); if fn then table.insert(parts,fn()) end else break end
  286. end
  287. if #parts > 0 then return table.concat(parts) end
  288. local m = OutputFolder:FindFirstChild(filename)
  289. if m then local fn=loadstring(m.Source); if fn then return fn() end end
  290. return "[]"
  291. end
  292. else
  293. FileSystem = {
  294. Enabled=true,
  295. Write=writefile or getgenv().writefile, Read=readfile or getgenv().readfile,
  296. List=listfiles or getgenv().listfiles, IsFolder=isfolder or getgenv().isfolder,
  297. MakeFolder=makefolder or getgenv().makefolder,
  298. }
  299. if not FileSystem.IsFolder(FOLDER_NAME) then FileSystem.MakeFolder(FOLDER_NAME) end
  300. end
  301.  
  302. -- ─────────────────────────────────────────────────────────────────────────────
  303. -- MODEL SELECTION
  304. -- ─────────────────────────────────────────────────────────────────────────────
  305.  
  306. local function selectModelLogic(model)
  307. if not model then return end
  308. selectedModel = model
  309. modelAnimType = detectModelType(selectedModel)
  310. StarterGui:SetCore("SendNotification", { Title="Target Locked ["..modelAnimType.."]"; Text=selectedModel.Name; Duration=3; })
  311. originalMotorStates = {}
  312. for _, c in ipairs(selectedModel:GetDescendants()) do
  313. if c:IsA("Motor6D") then
  314. originalMotorStates[c] = { Part0=c.Part0, Part1=c.Part1, C0=c.C0, C1=c.C1, Parent=c.Parent }
  315. end
  316. end
  317. modelBodyParts = {}
  318. for _, c in ipairs(selectedModel:GetDescendants()) do
  319. if c:IsA("BasePart") then table.insert(modelBodyParts, c) end
  320. end
  321. end
  322.  
  323. local function checkExplorerSelection()
  324. local ok, sel = pcall(function() return Selection:Get() end)
  325. if ok and sel and #sel > 0 then
  326. local target = sel[1]
  327. local model = target:IsA("Model") and target or target:FindFirstAncestorOfClass("Model")
  328. if model and model ~= player.Character then selectModelLogic(model); return true end
  329. end
  330. return false
  331. end
  332.  
  333. local function trySelect() return checkExplorerSelection() or selectedModel ~= nil end
  334.  
  335. local function restoreMotors(model)
  336. if not model then return end
  337. for _, d in pairs(model:GetDescendants()) do
  338. if d:IsA("Motor6D") and originalMotorStates[d] then
  339. local s = originalMotorStates[d]
  340. d.Part0, d.Part1, d.C0, d.C1, d.Parent = s.Part0, s.Part1, s.C0, s.C1, s.Parent
  341. end
  342. end
  343. end
  344.  
  345. -- ─────────────────────────────────────────────────────────────────────────────
  346. -- ACCESSORY COPYING (shared; resolver picks the right target part per clone type)
  347. -- ─────────────────────────────────────────────────────────────────────────────
  348. --[[
  349. partNameResolver(srcBodyPartName) → target part name on this clone.
  350. R6 clone : maps through r15ToR6PartName (e.g. "LeftUpperArm" → "Left Arm")
  351. R15 clone : identity pass-through (e.g. "LeftUpperArm" → "LeftUpperArm")
  352. ]]
  353. local function copyAccessoriesToClone(clone, resolver)
  354. if not clone or not player.Character then return end
  355. for _, c in ipairs(clone:GetChildren()) do if c:IsA("Accessory") then c:Destroy() end end
  356.  
  357. for _, item in ipairs(player.Character:GetChildren()) do
  358. if not item:IsA("Accessory") then continue end
  359. local handle = item:FindFirstChild("Handle"); if not handle then continue end
  360.  
  361. local srcPartName = nil
  362.  
  363. -- Method A: legacy Weld / WeldConstraint inside Handle
  364. for _, child in ipairs(handle:GetChildren()) do
  365. if child:IsA("Weld") or child:IsA("WeldConstraint") then
  366. local bp = (child.Part0 ~= handle and child.Part0) or (child.Part1 ~= handle and child.Part1)
  367. if bp then srcPartName = bp.Name; break end
  368. end
  369. end
  370.  
  371. -- Method B: RigidConstraint between Attachments
  372. if not srcPartName then
  373. for _, d in ipairs(item:GetDescendants()) do
  374. if d:IsA("RigidConstraint") then
  375. for _, att in ipairs({d.Attachment0, d.Attachment1}) do
  376. if att and att.Parent and att.Parent:IsA("BasePart") and att.Parent ~= handle then
  377. srcPartName = att.Parent.Name; break
  378. end
  379. end
  380. if srcPartName then break end
  381. end
  382. end
  383. end
  384.  
  385. -- Method C: matching Attachment name on character body part
  386. if not srcPartName then
  387. for _, att in ipairs(handle:GetChildren()) do
  388. if att:IsA("Attachment") then
  389. for _, bp in ipairs(player.Character:GetChildren()) do
  390. if bp:IsA("BasePart") and bp ~= handle and bp:FindFirstChild(att.Name) then
  391. srcPartName = bp.Name; break
  392. end
  393. end
  394. if srcPartName then break end
  395. end
  396. end
  397. end
  398.  
  399. srcPartName = srcPartName or "Head"
  400. local targetPart = clone:FindFirstChild(resolver(srcPartName))
  401. if not targetPart then continue end
  402.  
  403. local accClone = item:Clone()
  404. local cloneHandle = accClone:FindFirstChild("Handle")
  405. if not cloneHandle then accClone:Destroy(); continue end
  406.  
  407. cloneHandle.CanCollide = false
  408. cloneHandle.Anchored = false
  409. cloneHandle.Massless = true
  410.  
  411. for _, child in ipairs(cloneHandle:GetChildren()) do
  412. if child:IsA("Weld") or child:IsA("WeldConstraint") or child:IsA("RigidConstraint") then
  413. child:Destroy()
  414. end
  415. end
  416.  
  417. local origBP = player.Character:FindFirstChild(srcPartName)
  418. local bpCF = (origBP and origBP ~= handle) and origBP.CFrame or targetPart.CFrame
  419. local relOffset = bpCF:Inverse() * handle.CFrame
  420.  
  421. local weld = Instance.new("Weld")
  422. weld.Name, weld.Part0, weld.Part1 = "AccessoryWeld", targetPart, cloneHandle
  423. weld.C0, weld.C1, weld.Parent = relOffset, CFrame.identity, cloneHandle
  424.  
  425. accClone.Parent = clone
  426. end
  427. end
  428.  
  429. local function r6Resolver(n) return r15ToR6PartName[n] or "Head" end
  430. local function r15Resolver(n) return n end
  431.  
  432. -- ─────────────────────────────────────────────────────────────────────────────
  433. -- R6 CLONE (hand-built dummy)
  434. -- ─────────────────────────────────────────────────────────────────────────────
  435.  
  436. local function applyAppearance(clone)
  437. local hum = clone and clone:FindFirstChildOfClass("Humanoid"); if not hum then return end
  438. local ok, desc = pcall(function() return Players:GetHumanoidDescriptionFromUserId(player.UserId) end)
  439. if ok and desc then pcall(function() hum:ApplyDescriptionClientServer(desc) end) end
  440. end
  441.  
  442. local function createR6Dummy()
  443. local d = Instance.new("Model"); d.Name = "R6_Clone"
  444. local function pt(name, size)
  445. local p = Instance.new("Part"); p.Name,p.Size=name,size
  446. p.TopSurface,p.BottomSurface=Enum.SurfaceType.Smooth,Enum.SurfaceType.Smooth
  447. p.CanCollide=false; p.Parent=d; return p
  448. end
  449. local function mo(name,p0,p1,c0,c1)
  450. local m=Instance.new("Motor6D"); m.Name,m.Part0,m.Part1,m.C0,m.C1,m.Parent=name,p0,p1,c0,c1,p0
  451. end
  452. local hrp=pt("HumanoidRootPart",Vector3.new(2,2,1)); hrp.Transparency=1
  453. local head=pt("Head",Vector3.new(2,1,1)); pt("Torso",Vector3.new(2,2,1))
  454. local torso=d:FindFirstChild("Torso")
  455. pt("Left Arm",Vector3.new(1,2,1)); pt("Right Arm",Vector3.new(1,2,1))
  456. pt("Left Leg",Vector3.new(1,2,1)); pt("Right Leg",Vector3.new(1,2,1))
  457. local hum=Instance.new("Humanoid"); hum.DisplayDistanceType=Enum.HumanoidDisplayDistanceType.None; hum.Parent=d
  458. local mesh=Instance.new("SpecialMesh"); mesh.MeshType=Enum.MeshType.Head; mesh.Scale=Vector3.new(1.25,1.25,1.25); mesh.Parent=head
  459. local lArm=d:FindFirstChild("Left Arm"); local rArm=d:FindFirstChild("Right Arm")
  460. local lLeg=d:FindFirstChild("Left Leg"); local rLeg=d:FindFirstChild("Right Leg")
  461. mo("Root Joint",hrp,torso,CFrame.new(0,0,0),CFrame.new(0,0,0))
  462. mo("Neck",torso,head,CFrame.new(0,1,0),CFrame.new(0,-0.5,0))
  463. mo("Left Shoulder",torso,lArm,CFrame.new(-1,0.5,0),CFrame.new(0.5,0.5,0))
  464. mo("Right Shoulder",torso,rArm,CFrame.new(1,0.5,0),CFrame.new(-0.5,0.5,0))
  465. mo("Left Hip",torso,lLeg,CFrame.new(-0.5,-1,0),CFrame.new(0,1,0))
  466. mo("Right Hip",torso,rLeg,CFrame.new(0.5,-1,0),CFrame.new(0,1,0))
  467. d.PrimaryPart = hrp; return d
  468. end
  469.  
  470. local function spawnCloneR6()
  471. if myCloneR6 then myCloneR6:Destroy() end
  472. character = player.Character or player.CharacterAdded:Wait()
  473. humanoidRootPart = character:FindFirstChild("HumanoidRootPart"); if not humanoidRootPart then return end
  474. myCloneR6 = createR6Dummy()
  475. local cr = myCloneR6:FindFirstChild("HumanoidRootPart")
  476. if cr then
  477. cr.CFrame = humanoidRootPart.CFrame * CFrame.new(0, 0, -CLONE_DISTANCE)
  478. cr.CFrame = CFrame.lookAt(cr.Position, humanoidRootPart.Position)
  479. end
  480. myCloneR6.Parent = workspace
  481. task.wait(0.1)
  482. applyAppearance(myCloneR6)
  483. copyAccessoriesToClone(myCloneR6, r6Resolver)
  484. end
  485.  
  486. -- ─────────────────────────────────────────────────────────────────────────────
  487. -- R15 CLONE (Moon Animator style — clone the actual character)
  488. -- ─────────────────────────────────────────────────────────────────────────────
  489. --[[
  490. Clones the live character, removes scripts, anchors every part (so no ragdoll),
  491. and captures rest-pose world CFrames for every R15 body part.
  492. Placed to the side of the player so both clones are visible simultaneously.
  493. ]]
  494. local function spawnCloneR15()
  495. if myCloneR15 then myCloneR15:Destroy() end
  496. character = player.Character or player.CharacterAdded:Wait()
  497. humanoidRootPart = character:FindFirstChild("HumanoidRootPart"); if not humanoidRootPart then return end
  498.  
  499. character.Archivable = true
  500. local clone = character:Clone()
  501. clone.Name = "R15_Clone"
  502.  
  503. -- Strip all scripts (prevents the Animate script from overriding poses)
  504. for _, obj in ipairs(clone:GetDescendants()) do
  505. if obj:IsA("LocalScript") or obj:IsA("Script") or obj:IsA("ModuleScript") then
  506. obj:Destroy()
  507. end
  508. end
  509. local animate = clone:FindFirstChild("Animate")
  510. if animate then animate:Destroy() end
  511.  
  512. -- Position offset from R6 clone (opposite side of player)
  513. local cloneRoot = clone:FindFirstChild("HumanoidRootPart")
  514. if cloneRoot then
  515. cloneRoot.CFrame = humanoidRootPart.CFrame * CFrame.new(CLONE_DISTANCE, 0, 0)
  516. cloneRoot.CFrame = CFrame.lookAt(cloneRoot.Position, humanoidRootPart.Position)
  517. end
  518.  
  519. -- Anchor all parts — no gravity, no physics, no ragdoll
  520. for _, part in ipairs(clone:GetDescendants()) do
  521. if part:IsA("BasePart") then
  522. part.Anchored = true
  523. part.CanCollide = false
  524. end
  525. end
  526.  
  527. clone.Parent = workspace
  528. myCloneR15 = clone
  529.  
  530. -- Capture rest pose NOW (before any animation is applied)
  531. r15RestPose = {}
  532. for _, partName in ipairs(r15PartNames) do
  533. local p = clone:FindFirstChild(partName)
  534. if p then r15RestPose[partName] = p.CFrame end
  535. end
  536. local hrpPart = clone:FindFirstChild("HumanoidRootPart")
  537. r15RestHRPCF = hrpPart and hrpPart.CFrame or CFrame.identity
  538.  
  539. -- Fix accessory welds: the cloned accessories' Part0 still points at the
  540. -- original character's body parts. copyAccessoriesToClone replaces them.
  541. task.wait(0.1)
  542. copyAccessoriesToClone(myCloneR15, r15Resolver)
  543. end
  544.  
  545. -- ─────────────────────────────────────────────────────────────────────────────
  546. -- SERIALIZATION
  547. -- ─────────────────────────────────────────────────────────────────────────────
  548.  
  549. local function serializeFrames(frames, animType)
  550. local data = { animType=animType, frames={} }
  551. for i, frame in ipairs(frames) do
  552. data.frames[i] = {}
  553. for pn, pd in pairs(frame) do data.frames[i][pn] = { pd.CFrame:components() } end
  554. end
  555. return HttpService:JSONEncode(data)
  556. end
  557.  
  558. local function deserializeFrames(json)
  559. local raw = HttpService:JSONDecode(json)
  560. local frames, animType = {}, "Unknown"
  561. if raw.animType and raw.frames then
  562. animType = raw.animType
  563. for i, rf in ipairs(raw.frames) do
  564. frames[i] = {}
  565. for pn, comps in pairs(rf) do frames[i][pn] = { CFrame=CFrame.new(unpack(comps)) } end
  566. end
  567. else
  568. for i, rf in ipairs(raw.frames or raw) do
  569. frames[i] = {}
  570. for pn, comps in pairs(rf) do frames[i][pn] = { CFrame=CFrame.new(unpack(comps)) } end
  571. end
  572. end
  573. return frames, animType
  574. end
  575.  
  576. -- ─────────────────────────────────────────────────────────────────────────────
  577. -- UI
  578. -- ─────────────────────────────────────────────────────────────────────────────
  579.  
  580. local function createUI()
  581. local gui = Instance.new("ScreenGui")
  582. gui.Name, gui.ResetOnSpawn = "AnimationStealer", false
  583. gui.Parent = player:WaitForChild("PlayerGui")
  584.  
  585. local mf = Instance.new("Frame")
  586. mf.Size = UDim2.new(0, 310, 0, 490)
  587. mf.Position = UDim2.new(0.5,-155,0.5,-245)
  588. mf.BackgroundColor3 = Color3.fromRGB(28,28,28)
  589. mf.BorderSizePixel = 1; mf.BorderColor3 = Color3.fromRGB(45,45,45)
  590. mf.Parent = gui
  591.  
  592. local tb = Instance.new("Frame")
  593. tb.Size = UDim2.new(1,0,0,28); tb.BackgroundColor3 = Color3.fromRGB(38,38,38)
  594. tb.BorderSizePixel = 0; tb.Parent = mf
  595.  
  596. local tl = Instance.new("TextLabel")
  597. tl.Size=UDim2.new(1,-10,1,0); tl.Position=UDim2.new(0,8,0,0)
  598. tl.BackgroundTransparency=1; tl.Text="Animation Stealer"
  599. tl.TextColor3=Color3.fromRGB(220,220,220); tl.TextSize=14
  600. tl.Font=Enum.Font.SourceSans; tl.TextXAlignment=Enum.TextXAlignment.Left
  601. tl.Parent=tb
  602.  
  603. tb.InputBegan:Connect(function(inp)
  604. if inp.UserInputType==Enum.UserInputType.MouseButton1 or inp.UserInputType==Enum.UserInputType.Touch then
  605. dragging=true; dragStart=inp.Position; startPos=mf.Position
  606. inp.Changed:Connect(function() if inp.UserInputState==Enum.UserInputState.End then dragging=false end end)
  607. end
  608. end)
  609. tb.InputChanged:Connect(function(inp)
  610. if inp.UserInputType==Enum.UserInputType.MouseMovement or inp.UserInputType==Enum.UserInputType.Touch then dragInput=inp end
  611. end)
  612. UserInputService.InputChanged:Connect(function(inp)
  613. if inp==dragInput and dragging then
  614. local d=inp.Position-dragStart
  615. mf.Position=UDim2.new(startPos.X.Scale,startPos.X.Offset+d.X,startPos.Y.Scale,startPos.Y.Offset+d.Y)
  616. end
  617. end)
  618.  
  619. local sl = Instance.new("TextLabel")
  620. sl.Size=UDim2.new(1,-16,0,22); sl.Position=UDim2.new(0,8,0,36)
  621. sl.BackgroundColor3=Color3.fromRGB(22,22,22); sl.BorderSizePixel=1; sl.BorderColor3=Color3.fromRGB(40,40,40)
  622. sl.Text=" idle"; sl.TextColor3=Color3.fromRGB(160,160,160); sl.TextSize=13
  623. sl.Font=Enum.Font.Code; sl.TextXAlignment=Enum.TextXAlignment.Left
  624. sl.Parent=mf
  625.  
  626. local function btn(text, pos, color)
  627. local b = Instance.new("TextButton")
  628. b.Size=UDim2.new(1,-16,0,32); b.Position=pos
  629. b.BackgroundColor3=color; b.BorderSizePixel=1
  630. b.BorderColor3=Color3.fromRGB(math.max(0,color.R*255-20),math.max(0,color.G*255-20),math.max(0,color.B*255-20))
  631. b.Text=text; b.TextColor3=Color3.fromRGB(240,240,240); b.TextSize=13; b.Font=Enum.Font.SourceSansBold
  632. b.Parent=mf
  633. b.MouseButton1Down:Connect(function() b.BackgroundColor3=Color3.fromRGB(math.max(0,color.R*255-15),math.max(0,color.G*255-15),math.max(0,color.B*255-15)) end)
  634. b.MouseButton1Up:Connect(function() b.BackgroundColor3=color end)
  635. b.MouseLeave:Connect(function() b.BackgroundColor3=color end)
  636. return b
  637. end
  638.  
  639. -- Half-width button: each takes exactly half the usable width minus a 4px gap
  640. -- Usable = 310 - 16 = 294; half = (294 - 4) / 2 = 145
  641. local function halfBtn(text, xOff, yOff, color)
  642. local b = Instance.new("TextButton")
  643. b.Size=UDim2.new(0,145,0,32); b.Position=UDim2.new(0,xOff,0,yOff)
  644. b.BackgroundColor3=color; b.BorderSizePixel=1
  645. b.BorderColor3=Color3.fromRGB(math.max(0,color.R*255-20),math.max(0,color.G*255-20),math.max(0,color.B*255-20))
  646. b.Text=text; b.TextColor3=Color3.fromRGB(240,240,240); b.TextSize=13; b.Font=Enum.Font.SourceSansBold
  647. b.Parent=mf
  648. b.MouseButton1Down:Connect(function() b.BackgroundColor3=Color3.fromRGB(math.max(0,color.R*255-15),math.max(0,color.G*255-15),math.max(0,color.B*255-15)) end)
  649. b.MouseButton1Up:Connect(function() b.BackgroundColor3=color end)
  650. b.MouseLeave:Connect(function() b.BackgroundColor3=color end)
  651. return b
  652. end
  653.  
  654. local function sep(y)
  655. local s=Instance.new("Frame"); s.Size=UDim2.new(1,-16,0,1); s.Position=UDim2.new(0,8,0,y)
  656. s.BackgroundColor3=Color3.fromRGB(50,50,50); s.BorderSizePixel=0; s.Parent=mf
  657. end
  658.  
  659. local bPlayer = btn("Record Player", UDim2.new(0,8,0,68), Color3.fromRGB(55,85,150))
  660. local bModel = btn("Record Model", UDim2.new(0,8,0,106), Color3.fromRGB(150,55,100))
  661. local bBoth = btn("Record Both", UDim2.new(0,8,0,144), Color3.fromRGB(120,55,150))
  662. sep(186)
  663. local bStop = btn("Stop Recording", UDim2.new(0,8,0,196), Color3.fromRGB(150,50,50))
  664. local bRefresh = btn("Refresh Selection", UDim2.new(0,8,0,234), Color3.fromRGB(50,110,150))
  665. sep(276)
  666.  
  667. local inName = Instance.new("TextBox")
  668. inName.Size=UDim2.new(1,-16,0,28); inName.Position=UDim2.new(0,8,0,286)
  669. inName.Text=""; inName.PlaceholderText="filename"
  670. inName.BackgroundColor3=Color3.fromRGB(22,22,22); inName.BorderSizePixel=1; inName.BorderColor3=Color3.fromRGB(40,40,40)
  671. inName.TextColor3=Color3.fromRGB(230,230,230); inName.PlaceholderColor3=Color3.fromRGB(100,100,100)
  672. inName.TextSize=13; inName.Font=Enum.Font.Code; inName.Parent=mf
  673. Instance.new("UIPadding",inName).PaddingLeft=UDim.new(0,6)
  674.  
  675. local bSave = btn("Save", UDim2.new(0,8,0,320), Color3.fromRGB(50,130,70))
  676.  
  677. -- ── Split play row (y=358): left = R6 (purple), right = R15 (teal) ─────
  678. -- Left : x=8, width=145
  679. -- Right : x=161 (8 + 145 + 8 gap), width=145 → right edge = 161+145 = 306 ≤ 310-4=306 ✓
  680. local bPlayR6 = halfBtn("▶ Play R6", 8, 358, Color3.fromRGB(90,60,140))
  681. local bPlayR15 = halfBtn("▶ Play R15", 157, 358, Color3.fromRGB(40,115,105))
  682.  
  683. sep(400)
  684.  
  685. local lf = Instance.new("ScrollingFrame")
  686. lf.Size=UDim2.new(1,-16,0,82); lf.Position=UDim2.new(0,8,0,408)
  687. lf.BackgroundColor3=Color3.fromRGB(18,18,18); lf.BorderSizePixel=1; lf.BorderColor3=Color3.fromRGB(40,40,40)
  688. lf.ScrollBarThickness=6; lf.ScrollBarImageColor3=Color3.fromRGB(80,80,80)
  689. lf.CanvasSize=UDim2.new(0,0,0,0); lf.AutomaticCanvasSize=Enum.AutomaticSize.Y
  690. lf.Parent=mf
  691.  
  692. local ll=Instance.new("UIListLayout"); ll.Padding=UDim.new(0,2); ll.Parent=lf
  693. local lp=Instance.new("UIPadding"); lp.PaddingTop=UDim.new(0,4); lp.PaddingBottom=UDim.new(0,4)
  694. lp.PaddingLeft=UDim.new(0,4); lp.PaddingRight=UDim.new(0,4); lp.Parent=lf
  695.  
  696. return mf, sl, bPlayer, bModel, bBoth, bStop, bRefresh, bSave, bPlayR6, bPlayR15, inName, lf
  697. end
  698.  
  699. local mainGUI, statusLabel,
  700. btnPlayer, btnModel, btnBoth,
  701. btnStop, btnRefresh,
  702. btnSave, btnPlayR6, btnPlayR15,
  703. inputName, listFrame = createUI()
  704.  
  705. local function updateStatus(text, color)
  706. statusLabel.Text = " "..text
  707. if color then statusLabel.TextColor3 = color end
  708. end
  709.  
  710. -- ─────────────────────────────────────────────────────────────────────────────
  711. -- RECORDING
  712. -- ─────────────────────────────────────────────────────────────────────────────
  713.  
  714. function startRecording(mode)
  715. if isRecording then return end
  716. isRecording = true; recordingType = mode
  717. recordedFrames, recordedFramesBoth_Player, recordedFramesBoth_Model = {},{},{}
  718. recordTimestamps, recordTimestamps_Player, recordTimestamps_Model = {},{},{}
  719.  
  720. if mode=="Player" then
  721. playerAnimType = detectModelType(player.Character); sourceAnimType = playerAnimType
  722. elseif mode=="Model" and selectedModel then
  723. modelAnimType = detectModelType(selectedModel); sourceAnimType = modelAnimType
  724. elseif mode=="Both" then
  725. playerAnimType = detectModelType(player.Character)
  726. if selectedModel then modelAnimType = detectModelType(selectedModel) end
  727. sourceAnimType = "R6"
  728. end
  729.  
  730. playerBodyParts = {}
  731. if player.Character then
  732. for _, n in ipairs(bodyPartNames) do
  733. local p = player.Character:FindFirstChild(n)
  734. if p then table.insert(playerBodyParts, p) end
  735. end
  736. end
  737.  
  738. modelBodyParts = {}
  739. if selectedModel then
  740. for _, c in ipairs(selectedModel:GetDescendants()) do
  741. if c:IsA("BasePart") then table.insert(modelBodyParts, c) end
  742. end
  743. end
  744.  
  745. local tag = mode=="Both" and "[P:"..playerAnimType.." M:"..modelAnimType.."]" or "["..sourceAnimType.."]"
  746. updateStatus("recording "..tag, Color3.fromRGB(200,80,80))
  747.  
  748. recordConnection = RunService.RenderStepped:Connect(function()
  749. local t = os.clock()
  750.  
  751. if mode=="Player" or mode=="Both" then
  752. local f = {}
  753. for _, p in ipairs(playerBodyParts) do if p and p.Parent then f[p.Name]={CFrame=p.CFrame} end end
  754. if mode=="Player" then table.insert(recordedFrames,f); table.insert(recordTimestamps,t) end
  755. if mode=="Both" then table.insert(recordedFramesBoth_Player,f); table.insert(recordTimestamps_Player,t) end
  756. end
  757.  
  758. if (mode=="Model" or mode=="Both") and selectedModel then
  759. local f = {}
  760. for _, p in ipairs(modelBodyParts) do if p and p.Parent then f[p.Name]={CFrame=p.CFrame} end end
  761. if mode=="Model" then table.insert(recordedFrames,f); table.insert(recordTimestamps,t) end
  762. if mode=="Both" then table.insert(recordedFramesBoth_Model,f); table.insert(recordTimestamps_Model,t) end
  763. end
  764. end)
  765. end
  766.  
  767. function stopRecording()
  768. if not isRecording then return end
  769. isRecording = false
  770. if recordConnection then recordConnection:Disconnect() end
  771. if selectedModel then restoreMotors(selectedModel) end
  772. updateStatus("stopped", Color3.fromRGB(160,160,160))
  773. end
  774.  
  775. -- ─────────────────────────────────────────────────────────────────────────────
  776. -- PLAYBACK — R6 clone
  777. -- ─────────────────────────────────────────────────────────────────────────────
  778.  
  779. function replayOnCloneR6(data, animType, timestamps)
  780. animType = animType or sourceAnimType
  781. timestamps = timestamps or recordTimestamps
  782. if isRecording or isReplaying or not data or #data==0 then return end
  783. if not myCloneR6 then spawnCloneR6(); task.wait(0.1) end
  784. isReplaying = true
  785.  
  786. local recFPS = estimateFPS(timestamps)
  787. local framesToPlay = prepareForR6(data, animType, 60, recFPS)
  788. local tag = animType=="R15" and string.format(" [r15→r6 %.0ffps]",recFPS) or ""
  789. updateStatus("playing R6"..tag, Color3.fromRGB(80,200,100))
  790.  
  791. -- Anchor all R6 parts, refresh accessories, then destroy Motor6Ds
  792. for _, pn in ipairs(r6PartNames) do
  793. local p = myCloneR6:FindFirstChild(pn); if p then p.Anchored=true end
  794. end
  795. copyAccessoriesToClone(myCloneR6, r6Resolver)
  796. for _, d in ipairs(myCloneR6:GetDescendants()) do
  797. if d:IsA("Motor6D") then d:Destroy() end
  798. end
  799.  
  800. local cloneRoot = myCloneR6:FindFirstChild("HumanoidRootPart")
  801. local firstHRP = framesToPlay[1] and framesToPlay[1]["HumanoidRootPart"]
  802. local recStart = firstHRP and firstHRP.CFrame or CFrame.identity
  803. local offsetMat = cloneRoot.CFrame * recStart:Inverse()
  804.  
  805. local idx = 1
  806. replayConnection = RunService.RenderStepped:Connect(function()
  807. if idx <= #framesToPlay and myCloneR6 and myCloneR6.Parent then
  808. local fd = framesToPlay[idx]
  809. for _, pn in ipairs(r6PartNames) do
  810. local p = myCloneR6:FindFirstChild(pn)
  811. if p and fd[pn] then p.CFrame = offsetMat * fd[pn].CFrame end
  812. end
  813. idx = idx + 1
  814. else
  815. if replayConnection then replayConnection:Disconnect() end
  816. isReplaying = false; spawnCloneR6()
  817. updateStatus("idle", Color3.fromRGB(160,160,160))
  818. end
  819. end)
  820. end
  821.  
  822. -- ─────────────────────────────────────────────────────────────────────────────
  823. -- PLAYBACK — R15 clone
  824. -- ─────────────────────────────────────────────────────────────────────────────
  825.  
  826. function replayOnCloneR15(data, animType, timestamps)
  827. animType = animType or sourceAnimType
  828. timestamps = timestamps or recordTimestamps
  829. if isRecording or isReplaying or not data or #data==0 then return end
  830. -- Spawn/re-spawn to get a fresh rest pose before converting
  831. if not myCloneR15 then spawnCloneR15(); task.wait(0.2) end
  832. isReplaying = true
  833.  
  834. local recFPS = estimateFPS(timestamps)
  835. local framesToPlay = prepareForR15(data, animType, 60, recFPS)
  836. local tag = animType=="R6"
  837. and string.format(" [r6→r15 %.0ffps]",recFPS)
  838. or string.format(" [r15 %.0ffps]",recFPS)
  839. updateStatus("playing R15"..tag, Color3.fromRGB(80,200,160))
  840.  
  841. -- Refresh accessories, then destroy Motor6Ds (parts are already anchored)
  842. copyAccessoriesToClone(myCloneR15, r15Resolver)
  843. for _, d in ipairs(myCloneR15:GetDescendants()) do
  844. if d:IsA("Motor6D") then d:Destroy() end
  845. end
  846.  
  847. local cloneRoot = myCloneR15:FindFirstChild("HumanoidRootPart")
  848. local firstHRP = framesToPlay[1] and framesToPlay[1]["HumanoidRootPart"]
  849. local recStart = firstHRP and firstHRP.CFrame or CFrame.identity
  850. local offsetMat = (cloneRoot and cloneRoot.CFrame or CFrame.identity) * recStart:Inverse()
  851.  
  852. local idx = 1
  853. replayConnection = RunService.RenderStepped:Connect(function()
  854. if idx <= #framesToPlay and myCloneR15 and myCloneR15.Parent then
  855. local fd = framesToPlay[idx]
  856. for _, pn in ipairs(r15PartNames) do
  857. local p = myCloneR15:FindFirstChild(pn)
  858. if p and fd[pn] then p.CFrame = offsetMat * fd[pn].CFrame end
  859. end
  860. idx = idx + 1
  861. else
  862. if replayConnection then replayConnection:Disconnect() end
  863. isReplaying = false; spawnCloneR15()
  864. updateStatus("idle", Color3.fromRGB(160,160,160))
  865. end
  866. end)
  867. end
  868.  
  869. -- ─────────────────────────────────────────────────────────────────────────────
  870. -- FILE LIST
  871. -- ─────────────────────────────────────────────────────────────────────────────
  872.  
  873. local function refreshFileList()
  874. for _, v in pairs(listFrame:GetChildren()) do if v:IsA("TextButton") then v:Destroy() end end
  875. local files = FileSystem.List(FOLDER_NAME); if not files then return end
  876. for _, path in ipairs(files) do
  877. local fileName = path:match("([^/]+)%.json$")
  878. if fileName then
  879. local b = Instance.new("TextButton")
  880. b.Size=UDim2.new(1,-8,0,22); b.BackgroundColor3=Color3.fromRGB(32,32,32); b.BorderSizePixel=0
  881. b.Text=" "..fileName; b.TextColor3=Color3.fromRGB(200,200,200); b.TextSize=11
  882. b.Font=Enum.Font.Code; b.TextXAlignment=Enum.TextXAlignment.Left; b.Parent=listFrame
  883. b.MouseEnter:Connect(function() b.BackgroundColor3=Color3.fromRGB(42,42,42) end)
  884. b.MouseLeave:Connect(function() b.BackgroundColor3=Color3.fromRGB(32,32,32) end)
  885. b.MouseButton1Click:Connect(function()
  886. recordedFrames, sourceAnimType = deserializeFrames(FileSystem.Read(path))
  887. recordTimestamps = {}
  888. updateStatus("loaded: "..fileName, Color3.fromRGB(200,200,100))
  889. end)
  890. end
  891. end
  892. end
  893.  
  894. -- ─────────────────────────────────────────────────────────────────────────────
  895. -- BUTTON WIRING
  896. -- ─────────────────────────────────────────────────────────────────────────────
  897.  
  898. btnRefresh.MouseButton1Click:Connect(function()
  899. if checkExplorerSelection() then updateStatus("target locked",Color3.fromRGB(80,200,100))
  900. else updateStatus("select in explorer",Color3.fromRGB(200,140,60)) end
  901. end)
  902.  
  903. btnPlayer.MouseButton1Click:Connect(function() startRecording("Player") end)
  904.  
  905. btnModel.MouseButton1Click:Connect(function()
  906. if not trySelect() then updateStatus("select in explorer",Color3.fromRGB(200,100,60)); return end
  907. startRecording("Model")
  908. end)
  909.  
  910. btnBoth.MouseButton1Click:Connect(function()
  911. if not trySelect() then updateStatus("select in explorer",Color3.fromRGB(200,100,60)); return end
  912. startRecording("Both")
  913. end)
  914.  
  915. btnStop.MouseButton1Click:Connect(stopRecording)
  916.  
  917. btnSave.MouseButton1Click:Connect(function()
  918. if isRecording then stopRecording() end
  919. local name = inputName.Text ~= "" and inputName.Text or "anim_"..os.time()
  920. if recordingType=="Player" or recordingType=="Model" then
  921. if #recordedFrames > 0 then
  922. FileSystem.Write(FOLDER_NAME.."/"..name..".json", serializeFrames(recordedFrames,sourceAnimType))
  923. updateStatus("saved: "..name, Color3.fromRGB(80,200,100))
  924. end
  925. elseif recordingType=="Both" then
  926. if #recordedFramesBoth_Player > 0 then FileSystem.Write(FOLDER_NAME.."/"..name.."_player.json", serializeFrames(recordedFramesBoth_Player,playerAnimType)) end
  927. if #recordedFramesBoth_Model > 0 then FileSystem.Write(FOLDER_NAME.."/"..name.."_model.json", serializeFrames(recordedFramesBoth_Model,modelAnimType)) end
  928. updateStatus("saved both", Color3.fromRGB(80,200,100))
  929. end
  930. refreshFileList()
  931. end)
  932.  
  933. btnPlayR6.MouseButton1Click:Connect(function()
  934. replayOnCloneR6(recordedFrames, sourceAnimType, recordTimestamps)
  935. end)
  936.  
  937. btnPlayR15.MouseButton1Click:Connect(function()
  938. replayOnCloneR15(recordedFrames, sourceAnimType, recordTimestamps)
  939. end)
  940.  
  941. UserInputService.InputBegan:Connect(function(input, processed)
  942. if processed then return end
  943. if input.KeyCode == Enum.KeyCode.T then spawnCloneR6(); spawnCloneR15() end
  944. end)
  945.  
  946. -- ─────────────────────────────────────────────────────────────────────────────
  947. -- INIT
  948. -- ─────────────────────────────────────────────────────────────────────────────
  949.  
  950. spawnCloneR6()
  951. spawnCloneR15()
  952. refreshFileList()
  953. StarterGui:SetCore("SendNotification", { Title="Animation Stealer"; Text="Ready (R6 + R15)"; Duration=3; })
Advertisement
Comments
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
Add Comment
Please, Sign In to add comment