I don’t know how to use the coroutines, and I am getting nowhere with the wrapping function in the documentation. I think its not applicable to this scenario. I also don’t want to use the loop = true thing as I worry that will stop the loop for everyone. I say everyone as I noticed that the remote event will run two instances of the function when called twice, I worry that if one person changes the loop to false, person two will also get blocked. I will try to explain it again with the actual code this time.
game.ReplicatedStorage.StanceReseter.OnClientEvent:Connect(function(Player,Humanoid,Root,LHip,RHip)
if TruePlayer ~= Player then
Humanoid.CameraOffset = StanceOffset[1]
LHip.C0 = CF(-1, -1, 0) * CFANG(0, RAD(-90), 0)
LHip.C1 = CF(-0.5, 1, 0) * CFANG(0, RAD(-90), 0)
RHip.C0 = CF(1, -1, 0) * CFANG(RAD(-180), RAD(90), 0)
RHip.C1 = CF(0.5, 1, 0) * CFANG(RAD(-180), RAD(90), 0)
Root.C0 = CFANG(RAD(-90), 0, RAD(180))
end
end)
game.ReplicatedStorage.Stancer.OnClientEvent:Connect(function(Player,Name,Humanoid,Root,StanceChangeSpeed,Stance,PreviousStance,Neck,TCFM)
if TruePlayer ~= Player then
local PreviousOffset = Humanoid.CameraOffset
local PreviousRootP = Root.C0.p
local PreviousNeckP = Neck.C0.p
for X = 0, 90, 1.5 / StanceChangeSpeed do
local Alpha = Sine(X)
Humanoid.CameraOffset = PreviousOffset:lerp(StanceOffset[Stance+1], Alpha)
if Name == "Stand" then
if Stance ~= 0 then break end
Root.C0 = CF(PreviousRootP:lerp(VEC3(), Alpha)) * CFANG(RAD(-90), 0, RAD(180))
Neck.C0 = CF(PreviousNeckP:lerp(VEC3(0,1.5,0), Alpha))
elseif Name == "Crouch" then
if Stance ~= 1 then break end
Root.C0 = CF(PreviousRootP:lerp(VEC3(0, -1, 0), Alpha)) * CFANG(RAD(-90), 0, RAD(180))
if PreviousStance == 2 then
Neck.C0 = CF((PreviousNeckP*VEC3(1,1,-1)):lerp(VEC3(0,1.5,0), Alpha))
else
Neck.C0 = CF((PreviousNeckP):lerp(VEC3(0,1.5,0), Alpha))
end
elseif Name == "Prone" then
if Stance ~= 2 then break end
Root.C0 = CF(PreviousRootP:lerp(VEC3(0, -2.5, 1), Alpha)) * CFANG(RAD(180), 0, RAD(180))
Neck.C0 = CF((PreviousNeckP*VEC3(0,0,0)):lerp(VEC3(0, 1, 1), Alpha)) * CFANG(RAD(90), 0, 0)
end
RS:wait()
end
end
end)
and
game.ReplicatedStorage.Animator.OnClientEvent:Connect(function(Player, Joint, Jparent, NewC0, NewC1, Message, Duration,Gun_Ignore)
local Alpha
if Message == "Sine" then
Alpha = function(X) --Sine standin
return SIN(RAD(X))
end
else
Alpha = function(X) --Linear standin
return (X / 90)
end
end
if Player ~= game.Players.LocalPlayer and Joint ~= nil then
if Joint == "RightGrip" or Joint == "Left Hip" or Joint == "Right Hip" then
Joint = Player.Character[Jparent][Joint]
else
Joint = Gun_Ignore.PlayerFolder[Jparent][Joint]
end
local TweenIndicator = nil --At the current moment, this is how the script determines whether the function is already tweening a joint
local NewCode = math.random(-1e9, 1e9) --This creates a random code between -1000000000 and 1000000000
if (not Joint:FindFirstChild("TweenCode")) then --If the joint isn't being tweened, then
TweenIndicator = Instance.new("IntValue")
TweenIndicator.Name = "TweenCode"
TweenIndicator.Value = NewCode
TweenIndicator.Parent = Joint
else
TweenIndicator = Joint.TweenCode
TweenIndicator.Value = NewCode --If the joint is already being tweened, this will change the code, and the tween loop will stop
end
local MatrixCFrame = function(CFPos, CFTop, CFBack)
local CFRight = CFTop:Cross(CFBack)
return CF(
CFPos.x, CFPos.y, CFPos.z,
CFRight.x, CFTop.x, CFBack.x,
CFRight.y, CFTop.y, CFBack.y,
CFRight.z, CFTop.z, CFBack.z
)
end
local LerpCF = function(StartCF, EndCF, Alpha)
local StartTop = (StartCF * CFANG(RAD(90), 0, 0)).lookVector
local StartBack = -StartCF.lookVector
local EndTop = (EndCF * CFANG(RAD(90), 0, 0)).lookVector
local EndBack = -EndCF.lookVector
local StartPos = StartCF.p
local EndPos = EndCF.p
local NewCF = MatrixCFrame(
StartPos:lerp(EndPos, Alpha),
StartTop:lerp(EndTop, Alpha),
StartBack:lerp(EndBack, Alpha)
)
return NewCF
end
local StartC0 = Joint.C0
local StartC1 = Joint.C1
local X = 0
while true do
local NewX = X + math.min(1.5 / math.max(Duration, 0), 90)
X = (NewX > 90 and 90 or NewX)
if TweenIndicator.Value ~= NewCode then break end --This makes sure that another tween wasn't called on the same joint
if NewC0 then Joint.C0 = LerpCF(StartC0, NewC0, Alpha(X)) end
if NewC1 then Joint.C1 = LerpCF(StartC1, NewC1, Alpha(X)) end
if X == 90 then break end
RS:wait() --This makes the for loop step every 1/60th of a second
end
if TweenIndicator.Value == NewCode then --If this tween functions was the last one called on a joint then it will remove the code
TweenIndicator:Destroy()
end
end
end)
I will provide detailed explanations for what the code is doing if you want so. But here is what is important:
When Stancer is called while the stancer loop is playing, I need it to pause the loop. then create a new one. This prevents two loops being played on one person, which causes jittering. (will show if you want to see it)
If stancereseter is called then I need it to break the stancer loop and animator loop.
I tried having the loops in coroutines, but yielding them did not work. I will continue to work on this while I wait for your response. Hear from you soon!