local function o(o,A)animation.AnimationId="\114\098\120\097\115\115\101\116\105\100\058\047\047"..A return o:LoadAnimation(animation)end local function A(o,A)A=A or 1 local P,c=o:ToEulerAnglesXYZ()return CFrame.new(o.Position)*CFrame.Angles(0,c*A,0)end local function P(o)if not o then return end local P=o-npcModel.PrimaryPart.Position local c=rotationOffset*CFrame.new(Vector3.new(),P.Unit)or rotationOffset if not waveAnimationTrack.IsPlaying then NPC.Root.Transform=A(c,TwistProportions.Root)NPC.Waist.Transform=A(c,TwistProportions.Waist)end NPC.Neck.Transform=A(c,waveAnimationTrack.IsPlaying and TwistProportions.Full or TwistProportions.Neck)return P.Magnitude end
-- Helper functions
local function loadAnimation(controller, animationId)
	animation.AnimationId = "rbxassetid://" .. animationId
	return controller:LoadAnimation(animation)
end

local function isolateAndDampenYAngle(targetCFrame, proportionMultiplier)
	proportionMultiplier = proportionMultiplier or 1
	local _, y = targetCFrame:ToEulerAnglesXYZ()

	return CFrame.new(targetCFrame.Position) * CFrame.Angles(0, y * proportionMultiplier, 0)
end

local function makeNPCLookAt(lookAtPosition)
	if not lookAtPosition then
		return
	end

	local differenceVector = lookAtPosition - npcModel.PrimaryPart.Position
	local targetCFrame = rotationOffset * CFrame.new(Vector3.new(), differenceVector.Unit) or rotationOffset

	-- Let the waving animation move the body
	if not waveAnimationTrack.IsPlaying then
		NPC.Root.Transform = isolateAndDampenYAngle(targetCFrame, TwistProportions.Root)
		NPC.Waist.Transform = isolateAndDampenYAngle(targetCFrame, TwistProportions.Waist)
	end
	NPC.Neck.Transform = isolateAndDampenYAngle(
		targetCFrame,
		waveAnimationTrack.IsPlaying and TwistProportions.Full or TwistProportions.Neck
	)

	return differenceVector.Magnitude
end
