Skip to content

Instantly share code, notes, and snippets.

@eldonwilliams
Created February 6, 2022 07:05
Show Gist options
  • Save eldonwilliams/c49b2804a361f32187bed48a191aa83b to your computer and use it in GitHub Desktop.
Save eldonwilliams/c49b2804a361f32187bed48a191aa83b to your computer and use it in GitHub Desktop.
local Players = game:GetService("Players")
local R15Blank = game:GetService("ReplicatedStorage"):WaitForChild("Assets"):WaitForChild("R15Blank")
local LoadCharacter = {}
-- Generally useful types
export type BrickColorID = number
export type AssetType = string
export type CharacterAsset = {
id: number,
assetType: {
name: AssetType,
id: number,
},
name: string,
}
export type CharacterAppearance = {
playerAvatarType: Enum.GameAvatarType,
defaultPantsApplied: boolean,
defaultShirtApplied: boolean,
scales: {
bodyType: number,
head: number,
height: number,
proportion: number,
depth: number,
width: number,
},
bodyColors: {
leftArmColorId: BrickColorID,
torsoColorId: BrickColorID,
rightArmColorId: BrickColorID,
headColorId: BrickColorID,
leftLegColorId: BrickColorID,
rightLeftColorId: BrickColorID,
},
assets: Array<CharacterAsset>,
}
-- Internal types
export type HumanoidDescriptionModifier = (description: HumanoidDescription) -> HumanoidDescription
local function doesPropertyExist(object: Instance, property: string)
local exists,_ = pcall(function()
assert(object[property], "oof")
end)
return exists
end
--[=[
Generates a character model from a HumanoidDescription object.
@param description HumanoidDescription --
@return Model
]=]
function LoadCharacter.fromHumanoidDescription(description: HumanoidDescription): Model
local cloneBlank = R15Blank:Clone()
if (not cloneBlank:IsDescendantOf(workspace)) then
cloneBlank.Parent = workspace
end
cloneBlank:FindFirstChild("Humanoid"):ApplyDescription(description)
return cloneBlank
end
--[=[
Generates a character model from a userId. The userId must exist within the game and whatever cavets Players:GetCharacterAppearanceInfoAsync() has.
Also note this function is more-or-less a binding around LoadCharacter.fromHumanoidDescription(), that may suit your needs
@param userId number -- This is the userId you wish to use
@param modifier HumanoidDescriptionModifier -- A function which can modify the humanoid description
@return Model
]=]
function LoadCharacter.fromUserId(userId: number, modifier: HumanoidDescriptionModifier): Model
local characterData: CharacterAppearance = Players:GetCharacterAppearanceInfoAsync(userId)
local description = Instance.new("HumanoidDescription")
for colorName, value in pairs(characterData.bodyColors) do
local colorProperty: string, _ = colorName:sub(1,-3):gsub("^%l", string.upper)
if (doesPropertyExist(description, colorProperty)) then
description[colorProperty] = BrickColor.new(value).Color
else
warn(colorProperty, "did not exist!")
end
end
for scaleName, value in pairs(characterData.scales) do
local scaleProperty: string, _ = (scaleName .. "Scale"):gsub("^%l", string.upper)
if (doesPropertyExist(description, scaleProperty)) then
description[scaleProperty] = value
else
warn(scaleProperty, "did not exist!")
end
end
for _, assetData in ipairs(characterData.assets) do
local assetTypeSpaceless: string, _ = assetData.assetType.name:gsub("%s+", "")
if (doesPropertyExist(description, assetTypeSpaceless)) then
if (assetTypeSpaceless:find("Accessory")) then
description[assetTypeSpaceless] = description[assetTypeSpaceless] .. "," .. assetData.id
continue
end
description[assetTypeSpaceless] = assetData.id
continue
end
if (doesPropertyExist(description, assetTypeSpaceless .. "Accessory")) then
description[assetTypeSpaceless .. "Accessory"] = description[assetTypeSpaceless .. "Accessory"] .. "," .. assetData.id
continue
end
warn(assetData.assetType.name, "did not exist!")
end
if (modifier and type(modifier) == "function") then
description = modifier(description)
end
return LoadCharacter.fromHumanoidDescription(description)
end
--[=[
Generates a character model from a Player object.
Also note this function is more-or-less a binding around LoadCharacter.fromHumanoidDescription() and LoadCharacter.fromUserId, which either may suit your needs
@param userId number -- This is the userId you wish to use
@param modifier HumanoidDescriptionModifier -- A function which can modify the humanoid description
@return Model
]=]
function LoadCharacter.fromPlayer(player: Player, modifier: HumanoidDescriptionModifier)
return LoadCharacter.fromUserId(player.UserId, modifier)
end
return LoadCharacter
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment