local g={AutoSaveProfiles=30;LoadProfileRepeatDelay=15,ForceLoadMaxSteps=4;AssumeDeadSessionLock=1800,IssueCountForCriticalState=5;IssueLast=120,CriticalStateLast=120}local X do local g={}function g.Disconnect(g)local X=g._listener if X~=nil then local m=g._listener_table for g=1,#m,1 do if X==m[g]then table.remove(m,g)break end end g._listener=nil end end function g.NewArrayScriptConnection(X,m)return{_listener=m,_listener_table=X;Disconnect=g.Disconnect}end local m={}function m.Connect(m,X)if type(X)~="\102\117\110\099\116\105\111\110"then error("\091\083\099\114\105\112\116\083\105\103\110\097\108\093\058 \079\110\108\121 \102\117\110\099\116\105\111\110\115 \099\097\110 \098\101 \112\097\115\115\101\100 \116\111 \083\099\114\105\112\116\083\105\103\110\097\108\058\067\111\110\110\101\099\116\040\041")end table.insert(m._listeners,X)return{_listener=X;_listener_table=m._listeners,Disconnect=g.Disconnect}end function m.Fire(g,...)for g,X in ipairs(g._listeners)do X(...)end end function m.NewScriptSignal()return{_listeners={},Connect=m.Connect,Fire=m.Fire}end local f=game:GetService("\082\117\110\083\101\114\118\105\099\101")local E=f.Heartbeat X={NewScriptSignal=m.NewScriptSignal,NewArrayScriptConnection=g.NewArrayScriptConnection,HeartbeatWait=function(g)if g==nil or g==0 then return E:Wait()else local X=0 while X<=g do local g=E:Wait()X=X+g end return X end end;ConnectToOnClose=function(g,X)if(game:GetService("\082\117\110\083\101\114\118\105\099\101")):IsStudio()==false or X==true then game:BindToClose(g)end end}end


local SETTINGS = {
	
	AutoSaveProfiles = 30, -- Seconds (This value may vary - ProfileService will split the auto save load evenly in the given time)
	LoadProfileRepeatDelay = 15, -- Seconds between successive DataStore calls for the same key
	ForceLoadMaxSteps = 4, -- Steps taken before ForceLoad request steals the active session for a profile
	AssumeDeadSessionLock = 30 * 60, -- (seconds) If a profile hasn't been updated for 30 minutes, assume the session lock is dead
	-- As of writing, os.time() is not completely reliable, so we can only assume session locks are dead after a significant amount of time.
	
	IssueCountForCriticalState = 5, -- Issues to collect to announce critical state
	IssueLast = 120, -- Seconds
	CriticalStateLast = 120, -- Seconds
	
}

local Madwork -- Standalone Madwork reference for portable version of ProfileService
do
	-- ScriptConnection object:
	local ScriptConnection = {
		-- _listener = function -- [function]
		-- _listener_table = {} -- [table] -- Table from which the function entry will be removed
	}
	
	function ScriptConnection:Disconnect()
		local listener = self._listener
		if listener ~= nil then
			local listener_table = self._listener_table
			for i = 1, #listener_table do
				if listener == listener_table[i] then
					table.remove(listener_table, i)
					break
				end
			end
			self._listener = nil
		end
	end
	
	function ScriptConnection.NewArrayScriptConnection(listener_table, listener) --> [ScriptConnection]
		return {
			_listener = listener,
			_listener_table = listener_table,
			Disconnect = ScriptConnection.Disconnect
		}
	end
	
	-- ScriptSignal object:
	local ScriptSignal = {
		-- _listeners = {}
	}
	
	function ScriptSignal:Connect(listener) --> [ScriptConnection]
		if type(listener) ~= "function" then
			error("[ScriptSignal]: Only functions can be passed to ScriptSignal:Connect()")
		end
		table.insert(self._listeners, listener)
		return {
			_listener = listener,
			_listener_table = self._listeners,
			Disconnect = ScriptConnection.Disconnect
		}
	end
	
	function ScriptSignal:Fire(...)
		for _, listener in ipairs(self._listeners) do
			listener(...)
		end
	end
	
	function ScriptSignal.NewScriptSignal() --> [ScriptSignal]
		return {
			_listeners = {},
			Connect = ScriptSignal.Connect,
			Fire = ScriptSignal.Fire
		}
	end
	
	local RunService = game:GetService("RunService")
	local Heartbeat = RunService.Heartbeat
	
	Madwork = {
		NewScriptSignal = ScriptSignal.NewScriptSignal,
		NewArrayScriptConnection = ScriptConnection.NewArrayScriptConnection,
		HeartbeatWait = function(wait_time) --> time_elapsed
			if wait_time == nil or wait_time == 0 then
				return Heartbeat:Wait()
			else
				local time_elapsed = 0
				while time_elapsed <= wait_time do
					local time_waited = Heartbeat:Wait()
					time_elapsed = time_elapsed + time_waited
				end
				return time_elapsed
			end
		end,
		ConnectToOnClose = function(task, run_in_studio_mode)
			if game:GetService("RunService"):IsStudio() == false or run_in_studio_mode == true then
				game:BindToClose(task)
			end
		end,
	}
end
