Good evening programmers! I’ve made this topic to ask how could I make this “pose” module a little more consistent?
I’m making a Pose module for a game that I’m working on that’ll require you to make poses to do certain things. (almost like shapeshifting) And, I want to create a default pose upon character respawning, so that they can default to that pose if they want to restart or something.
The current problem I come across is how can I make it so that it doesn’t just randomly offsets the limbs from a blank CFrame position, and instead offset the limbs from the root’s CFrame position.
Images to show what I mean
I do believe it’s because it’s executing from a script that’s parented to the StarterGui, but I suspect waiting until the character is added before running the function.
The current code of the script that's creating the default pose
-- Service
local ContextActionService = game:GetService("ContextActionService")
local TestService = game:GetService("TestService") -- Just debugss
local TweenService = game:GetService("TweenService")
local UserInputService = game:GetService("UserInputService")
-- Libraries
local Tools = script:WaitForChild('Tools')
local Util = script:WaitForChild("Util")
local CM_Enum = require(Util:WaitForChild("CM_Enum"))
local CurrentSettings = require(script:WaitForChild("Settings"))
local Pose = require(Util:WaitForChild("Pose"))
local Types = require(Util:WaitForChild("Types"))
local UIManager = require(Util:WaitForChild("UIManager"))
-- Variables
local Player = game:GetService("Players").LocalPlayer
local Character = Player.Character or Player.CharacterAppearanceLoaded:Wait()
-- skipped lines 20 to 29
-- Functions
-- skipped lines 32 to 120
-- Main Script
Pose.init(Character) -- "init" is just creating the default pose
The current code of the function that creates the default pose
function PoseHandler.init(character)
assert(typeof(character) == "Instance", "character: expected Instance, got " .. typeof(character))
assert(character:IsA("Model"), "character: expected Model, got " .. character.ClassName)
if Character ~= character then -- doing this so it doesn't overwrite Character if it's set already
Character = character
end
Humanoid = Character:WaitForChild("Humanoid") :: Humanoid
RootPart = Character:WaitForChild("HumanoidRootPart") :: Part
Torso = Character:WaitForChild("Torso") :: Part
for _, child in Character:GetChildren() do
local limb = Humanoid:GetLimb(child)
if limb ~= Enum.Limb.Unknown then
Limbs[limb.Name] = child
end
end
if (RootPart.CFrame.Position - Vector3.zero).Magnitude < 1 then
repeat
game:GetService("RunService").Heartbeat:Wait()
until (RootPart.CFrame.Position - Vector3.zero).Magnitude > 1
-- i thought this was it, but it didn't do anything at all
end
PoseHandler:AddPose("_default")
print("Initiated Default Pose")
end
Edit @ 2023-08-30T04:00:00Z
I forgot to leave some details about how it’s loaded. It gets loaded after pressing a button in the local script, like so:
local function ToggleTools(actionName: string, userState: Enum.UserInputState, input: InputObject)
if userState == Enum.UserInputState.Begin then
CurrentSettings.Enabled = not CurrentSettings.Enabled
if CurrentSettings.Enabled then
freezeCharacter()
game:GetService("RunService").Heartbeat:Wait()
Pose:LoadPose("_default")
local tool = _Tools[CurrentSettings.LastMode]
if tool then
tool:Disable()
end
UIManager:ShowUI()
else
unfreezeCharacter()
hideTools()
UIManager:HideUI()
end
end
end
The function that loads the pose:
function PoseHandler:LoadPose(poseName)
assert(typeof(poseName) == "string", "poseName: expected string, got " .. typeof(poseName))
if not Poses[poseName] then
return CM_Enum.LogType.Caution, "No pose named " .. poseName
end
local Pose = Poses[poseName]
local Root = Pose.Root
local LimbData = Pose.LimbData
local currRootCFrame = Root.CFrame
for limb, data in LimbData do
if limb:FindFirstAncestorOfClass("Model") == Character then
for property, value in pairs(data) do
limb[property] = value
end
print(Root.CFrame:ToWorldSpace(data.CFrame).Position)
limb.CFrame = Root.CFrame:ToWorldSpace(data.CFrame)
end
end
game:GetService("RunService").Heartbeat:Wait()
Root.CFrame = currRootCFrame
end