function Util.debugPrint(a,D)local r=""D=D or"  "local s local Y for a,N in pairs(a)do local o=type(N)local P,T=pcall(function()return tostring(a)end)if P then Y=T else Y="\091"..(type(a).."\093")end if o=="\116\097\098\108\101"then s=string.format("\n\037\115\037\115","",Util.debugPrint(N,D.."  "))else local a,D=pcall(function()return tostring(N)end)if a then s=D else s="\091"..(type(N).."\093")end end r=string.format("\037\115\037\115\037\115\058 \037\115\n",r,D,Y,s)end return r end function Util.tableToString(a,D)local r=""D=D or"  "local s for a,Y in pairs(a)do local N=type(Y)if N=="\116\097\098\108\101"then s=string.format("\n\037\115\037\115","",Util.tableToString(Y,D.."  "))elseif N=="\110\105\108"then s="\091\110\105\108\093"elseif N=="\115\116\114\105\110\103"then s=string.format("\"\037\115\"",Y)elseif N=="\098\111\111\108\101\097\110"then s=Util.boolToString(Y)elseif N=="\117\115\101\114\100\097\116\097"then s="\091\085\083\069\082\068\065\084\065\093"elseif N=="\102\117\110\099\116\105\111\110"then s="\091\070\085\078\067\084\073\079\078\093"else s=Y end a=tostring(a)r=string.format("\037\115\037\115\037\115\058 \037\115\n",r,D,a,s)end return r end function Util.newRemoteEvent(a,D)local r=D:FindFirstChild(a)if r then Log.Warn.Util("\082\101\109\111\116\101\069\118\101\110\116 \037\115 \117\110\100\101\114 \037\115 \097\108\114\101\097\100\121 \101\120\105\115\116\115",a,D.Name)return r end local s=Instance.new("\082\101\109\111\116\101\069\118\101\110\116",D)s.Name=a return s end function Util.isPlayerInGroup(a,D)for D,r in ipairs(D)do if a:IsInGroup(r)then return true end end end function Util.isPlayerIDInTable(a,D)for D,r in ipairs(D)do if a.UserId==r then return true end end end function Util.lerp(a,D,r)return a*(1-r)+D*r end function Util.getClientFocus()return(CollectionService:GetTagged(Util._clientFocusTag))[1]end function Util.setClientFocus(a)if RunService:IsClient()then for a,D in ipairs(CollectionService:GetTagged(Util._clientFocusTag))do CollectionService:RemoveTag(D,Util._clientFocusTag)end CollectionService:AddTag(a,Util._clientFocusTag)end end Util.highestBotNum=150 function Util.playerIsBot(a)local D=tonumber(string.sub(a.Name,11))if D~=nil and(string.len(a.Name)>10 and(string.sub(a.Name,1,10)=="\114\098\120\114\101\102\116\101\115\116"and(D<=Util.highestBotNum and D>=1)))then return true end return false end function Util.playerIsAlive(a)if a and a.Character then local D=a.Character:FindFirstChildOfClass("\072\117\109\097\110\111\105\100")if D and D:GetState()~=Enum.HumanoidStateType.Dead then return true end end return false end function Util.ancestorHasTag(a,D)local r=a while r do if CollectionService:HasTag(r,D)then return true elseif not r.Parent then return false else r=r.Parent end end return false end function Util.getTableKeys(a)local D={}for a in pairs(a)do table.insert(D,a)end return D end function Util.loadCharacter(a)if Conf.force_rthro then local D=Conf.avatarOutfits local r=a.UserId local s=D[r%(#D-1)+1]local Y=Players:GetHumanoidDescriptionFromUserId(a.UserId)local N=Players:GetHumanoidDescriptionFromOutfitId(s)for a,D in pairs(Conf.avatarAnimations)do N[a]=D end local o=Y:GetEquippedEmotes()N:SetEquippedEmotes(o)a:LoadCharacterWithHumanoidDescription(N)else a:LoadCharacter()end end

function Util.debugPrint(tbl, indent)
	local out = ""

	indent = indent or "  "
	local vStr
	local kStr

	for k,v in pairs(tbl) do
		local t = type(v)

		local kConversionSuccess, kConversionResult = pcall(function() return tostring(k) end)
		if kConversionSuccess then
			kStr = kConversionResult
		else
			kStr = "[" .. type(k) .. "]"
		end

		if t == "table" then
			vStr = string.format("\n%s%s", "", Util.debugPrint(v, indent .. "  "))
		else
			local vConversionSuccess, vConversionResult = pcall(function() return tostring(v) end)
			if vConversionSuccess then
				vStr = vConversionResult
			else
				vStr = "[" .. type(v) .. "]"
			end
		end

		out = string.format("%s%s%s: %s\n", out, indent, kStr, vStr)
	end

	return out
end

function Util.tableToString(tbl, indent)
	local out = ""

	indent = indent or "  "
	local vStr

	for k,v in pairs(tbl) do
		local t = type(v)

		if t == "table" then
			vStr = string.format("\n%s%s", "", Util.tableToString(v, indent .. "  "))

		elseif t == "nil" then
			vStr = "[nil]"

		elseif t == "string" then
			vStr = string.format("\"%s\"", v)

		elseif t == "boolean" then
			vStr = Util.boolToString(v)

		elseif t == "userdata" then
			vStr = "[USERDATA]"

		elseif t == "function" then
			vStr = "[FUNCTION]"

		else
			vStr = v
		end

		k = tostring(k)

		out = string.format("%s%s%s: %s\n", out, indent, k, vStr)
	end

	return out
end

function Util.newRemoteEvent(name, parent)
	local existing = parent:FindFirstChild(name)

	if existing then
		Log.Warn.Util("RemoteEvent %s under %s already exists", name, parent.Name)

		return existing
	end

	local event = Instance.new("RemoteEvent", parent)
	event.Name = name

	return event
end

function Util.isPlayerInGroup(player, groups)
	for _, groupId in ipairs(groups) do
		if player:IsInGroup(groupId) then
			return true
		end
	end
end

function Util.isPlayerIDInTable(player, ids)
	for _, id in ipairs(ids) do
		if player.UserId == id then
			return true
		end
	end
end

function Util.lerp(start, stop, t)
	return start * (1 - t) + stop * t
end

function Util.getClientFocus()
	return CollectionService:GetTagged(Util._clientFocusTag)[1]
end

function Util.setClientFocus(instance)
	if RunService:IsClient() then
		-- Remove any tags
		for _, obj in ipairs(CollectionService:GetTagged(Util._clientFocusTag)) do
			CollectionService:RemoveTag(obj, Util._clientFocusTag)
		end

		-- Tag the specified object
		CollectionService:AddTag(instance, Util._clientFocusTag)
	end
end

Util.highestBotNum = 150
function Util.playerIsBot(player)
	local numOnEnd = tonumber(string.sub(player.Name, 11))
	if numOnEnd ~= nil and
	   string.len(player.Name) > 10 and
	   string.sub(player.Name, 1, 10) == "rbxreftest" and
	   numOnEnd <= Util.highestBotNum and
	   numOnEnd >= 1
	then
		return true
	end
	return false
end

function Util.playerIsAlive(player)
	if player and player.Character then
		local humanoid = player.Character:FindFirstChildOfClass("Humanoid")
		if humanoid and humanoid:GetState() ~= Enum.HumanoidStateType.Dead then
			return true
		end
	end
	return false
end

function Util.ancestorHasTag(instance, tag)
	local currentInstance = instance
	while currentInstance do
		if CollectionService:HasTag(currentInstance, tag) then
			return true
		elseif not currentInstance.Parent then
			return false
		else
			currentInstance = currentInstance.Parent
		end
	end

	return false
end

function Util.getTableKeys(tbl)
	local keys = {}

	for k in pairs(tbl) do
		table.insert(keys, k)
	end

	return keys
end

function Util.loadCharacter(player)
	if Conf.force_rthro then
		local avatars = Conf.avatarOutfits
		local effectiveId = player.UserId
		local outfitId = avatars[(effectiveId % (#avatars - 1)) + 1]

		local playerDesc = Players:GetHumanoidDescriptionFromUserId(player.UserId)
		local desc = Players:GetHumanoidDescriptionFromOutfitId(outfitId)

		-- Load animations from configuration
		for property, value in pairs(Conf.avatarAnimations) do
			desc[property] = value
		end

		local emotes = playerDesc:GetEquippedEmotes()
		desc:SetEquippedEmotes(emotes)

		player:LoadCharacterWithHumanoidDescription(desc)
	else
		player:LoadCharacter()
	end
end
