-
-
Save RuizuKun-Dev/c1ae8b10a1be40c8c879f21b2e85fb3a to your computer and use it in GitHub Desktop.
Adjusts Roblox Rthro avatars so that their height scales match a 5 stud high R15 rig
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local CLASSIC_HEIGHT = 5 | |
local function getObjectValue(parent: Instance, name: string, default) | |
local found = parent:FindFirstChild(name) | |
if found then | |
return found.Value | |
end | |
return default | |
end | |
local function matchHeadToMesh(head, headMesh) | |
for _, child: Instance in pairs(head:GetChildren()) do | |
if child:IsA("Attachment") and not headMesh:FindFirstChild(child.Name) then | |
local Attacthment: Attacthment = child | |
local vec3Copy = Instance.new("Vector3Value") | |
vec3Copy.Name = Attacthment.Name | |
vec3Copy.Value = Attacthment.Position | |
vec3Copy.Parent = headMesh | |
end | |
end | |
local partScaleType = head:FindFirstChild("AvatarPartScaleType") | |
if partScaleType and not headMesh:FindFirstChild("AvatarPartScaleType") then | |
partScaleType:Clone().Parent = headMesh | |
end | |
end | |
local function getMaxHeight(humanoid: Humanoid) | |
local humanoidRootPart = humanoid.RootPart | |
local character = humanoid.Parent | |
local upperTorso = character.UpperTorso | |
local head = character.Head | |
local root = character.LowerTorso.Root | |
local waist = upperTorso.Waist | |
local neck = head.Neck | |
-- part0 * c0 == part1 * c1 | |
local lowerTorsoCF = root.C0 * root.C1:Inverse() | |
local upperTorsoCF = lowerTorsoCF * waist.C0 * waist.C1:Inverse() | |
local headCF = upperTorsoCF * neck.C0 * neck.C1:Inverse() | |
local upperTorsoTop = upperTorsoCF.Y + upperTorso.Size.Y / 2 | |
local headTop = headCF.Y + head.Size.Y / 2 | |
-- Sometimes the upper torso is higher than the head. | |
-- For example: https://www.roblox.com/bundles/429/Magma-Fiend | |
return math.max(upperTorsoTop, headTop) + humanoidRootPart.Size.Y / 2 + humanoid.HipHeight | |
end | |
local function rthroScaleFix(character: Model) | |
local humanoid = character.Humanoid | |
local humanoidRootPart = humanoid.RootPart | |
local floorCF = humanoidRootPart.CFrame * CFrame.new(0, -(humanoidRootPart.Size.Y / 2 + humanoid.HipHeight), 0) | |
local height = getMaxHeight(humanoid) | |
local scale = (CLASSIC_HEIGHT / height) * getObjectValue(humanoid, "BodyHeightScale", 1) | |
local head = character.Head | |
local headMesh = head:FindFirstChildWhichIsA("SpecialMesh") | |
local isFileMesh = (headMesh.MeshType == Enum.MeshType.FileMesh) | |
local accessories = {} | |
for _, child: Instance in pairs(character:GetChildren()) do | |
if child:IsA("Accessory") then | |
local Accessory: Accessory = child | |
local handle = Accessory:FindFirstChildWhichIsA("BasePart") | |
local weld = handle:FindFirstChild("AccessoryWeld") | |
weld:Destroy() | |
Accessory.Parent = nil | |
accessories[Accessory] = true | |
end | |
end | |
matchHeadToMesh(head, headMesh) | |
for _, child: Instance in pairs(character:GetDescendants()) do | |
if child:IsA("Motor6D") then | |
local Motor6D: Motor6D= child | |
local p0 = Motor6D.C0.Position | |
local p1 = Motor6D.C1.Position | |
Motor6D.C0 = (Motor6D.C0 - p0) + p0 * scale | |
Motor6D.C1 = (Motor6D.C1 - p1) + p1 * scale | |
elseif child:IsA("Attachment") then | |
local Attachment: Attachment = child | |
Attachment.Position = Attachment.Position * scale | |
Attachment.OriginalPosition.Value = Attachment.OriginalPosition.Value * scale | |
elseif child.Name == "OriginalSize" then | |
local parent = child.Parent | |
if parent:IsA("BasePart") then | |
parent.Size = parent.Size * scale | |
child.Value = child.Value * scale | |
elseif parent == headMesh then | |
for _, v3 in pairs(parent:GetChildren()) do | |
if v3:IsA("Vector3Value") and v3 ~= child then | |
v3.Value = v3.Value * scale | |
end | |
end | |
if isFileMesh then | |
parent.Scale = parent.Scale * scale | |
child.Value = child.Value * scale | |
end | |
end | |
end | |
end | |
for accessory: Accessory, _ in pairs(accessories) do | |
local handle: BasePart = accessory:FindFirstChildWhichIsA("BasePart") | |
handle.OriginalSize.Value = handle.OriginalSize.Value * scale | |
humanoid:AddAccessory(accessory) | |
end | |
humanoid.HipHeight = humanoid.HipHeight * scale | |
humanoidRootPart.CFrame = floorCF * CFrame.new(0, humanoidRootPart.Size.Y / 2 + humanoid.HipHeight, 0) | |
end | |
return rthroScaleFix |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment