sm64-roblox-liberty-prime/server/StarterCharacter/Appearance/init.server.lua
2023-07-08 18:42:28 -05:00

150 lines
3.1 KiB
Lua

--!strict
local Players = game:GetService("Players")
local character: Instance = assert(script.Parent)
assert(character:IsA("Model"), "Not a character")
local player = Players:GetPlayerFromCharacter(character)
assert(player, "No player!")
local userId = player.UserId
local hDesc: HumanoidDescription?
local metalPointers = {} :: {
[MeshPart]: {
Metal: SurfaceAppearance?,
},
}
local function updateMetal(part: MeshPart)
local isMetal = character:GetAttribute("Metal")
local ptr = metalPointers[part]
if ptr == nil then
ptr = {}
metalPointers[part] = ptr
end
if isMetal and not ptr.Metal then
local surface = script.METAL_MARIO:Clone()
surface.Parent = part
ptr.Metal = surface
elseif ptr.Metal and not isMetal then
ptr.Metal:Destroy()
ptr.Metal = nil
end
end
local function onMetalChanged()
for meshPart in metalPointers do
updateMetal(meshPart)
end
end
local function onDescendantAdded(desc: Instance)
if desc:IsA("BasePart") then
if desc.CollisionGroup ~= "Player" then
local canCollide = desc:GetPropertyChangedSignal("CanCollide")
desc.CollisionGroup = "Player"
desc.CanQuery = false
desc.CanTouch = false
desc.Massless = true
canCollide:Connect(function()
desc.CanCollide = false
end)
desc.CanCollide = false
end
if desc:IsA("MeshPart") then
updateMetal(desc)
end
end
end
local function onDescendantRemoving(desc: Instance)
if desc:IsA("MeshPart") then
metalPointers[desc] = nil
end
end
local metalListener = character:GetAttributeChangedSignal("Metal")
metalListener:Connect(onMetalChanged)
for i, desc in character:GetDescendants() do
task.spawn(onDescendantAdded, desc)
end
character:SetAttribute("TimeScale", 1)
character.DescendantAdded:Connect(onDescendantAdded)
character.DescendantRemoving:Connect(onDescendantRemoving)
local function reload()
character:ScaleTo(1)
task.spawn(function()
for i = 1, 5 do
character:PivotTo(CFrame.new(0, 100, 0))
task.wait()
end
end)
for retry = 1, 10 do
local success, result = pcall(function()
return Players:GetHumanoidDescriptionFromUserId(userId)
end)
if success then
hDesc = result
break
else
task.wait(retry / 2)
end
end
if hDesc then
hDesc.HeadScale = 1.8
hDesc.WidthScale = 1.3
hDesc.DepthScale = 1.4
hDesc.HeightScale = 1.2
hDesc.BodyTypeScale = 0
hDesc.ProportionScale = 0
else
return
end
local humanoid = character:WaitForChild("Humanoid")
assert(hDesc)
if humanoid:IsA("Humanoid") then
while not humanoid.RootPart do
humanoid.Changed:Wait()
end
local rootPart = humanoid.RootPart
assert(rootPart, "No HumanoidRootPart??")
local particles = rootPart:FindFirstChild("Particles")
humanoid:ApplyDescription(hDesc)
if particles and particles:IsA("Attachment") then
local floorDec = humanoid.HipHeight + (rootPart.Size.Y / 2)
local pos = Vector3.new(0, -floorDec, 0)
rootPart.PivotOffset = CFrame.new(pos)
particles.Position = pos
end
end
end
local reset = Instance.new("RemoteEvent")
reset.Parent = character
reset.Name = "Reset"
reset.OnServerEvent:Connect(function(player)
if player == Players:GetPlayerFromCharacter(character) then
reload()
end
end)
task.spawn(reload)