local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local WalkSpeedStore = DataStoreService:GetDataStore("WalkSpeedDataStore")
local CashStore = DataStoreService:GetDataStore("CashDataStore")
local RebirthStore = DataStoreService:GetDataStore("RebirthDataStore")

local MAX_SPEED = 9e99
local GROUP_ID = 36035362 
local INCREMENT_NON_GROUP = 0.05
local INCREMENT_GROUP = 0.1
local OFFLINE_INCREMENT = 1 / 200 
local BASE_REBIRTH_COST = 10000

local offlineGainValue = ReplicatedStorage:FindFirstChild("OfflineGain")
if not offlineGainValue then
	offlineGainValue = Instance.new("NumberValue")
	offlineGainValue.Name = "OfflineGain"
	offlineGainValue.Value = 0
	offlineGainValue.Parent = ReplicatedStorage
end

local rebirthEvent = Instance.new("RemoteEvent")
rebirthEvent.Name = "RebirthEvent"
rebirthEvent.Parent = ReplicatedStorage

local function applyDiminishingReturn(current, gain)
	local distance = MAX_SPEED - current
	if distance <= 0 then return 0 end
	return gain * (distance / MAX_SPEED)
end

local function loadSpeed(player)
	local data
	local success = pcall(function()
		data = WalkSpeedStore:GetAsync(player.UserId)
	end)
	if success and data then
		return data.Speed or 0.00, data.LastLogout or os.time()
	else
		return 0.00, os.time()
	end
end

local function saveSpeed(player, speed)
	pcall(function()
		WalkSpeedStore:SetAsync(player.UserId, {Speed = speed, LastLogout = os.time()})
	end)
end

local function loadCash(player)
	local cash
	local success = pcall(function()
		cash = CashStore:GetAsync(player.UserId)
	end)
	if success and cash then
		return cash
	else
		return 0
	end
end

local function saveCash(player, cash)
	pcall(function()
		CashStore:SetAsync(player.UserId, cash)
	end)
end

local function loadRebirths(player)
	local rebirths
	local success = pcall(function()
		rebirths = RebirthStore:GetAsync(player.UserId)
	end)
	if success and rebirths then
		return rebirths
	else
		return 0
	end
end

local function saveRebirths(player, rebirths)
	pcall(function()
		RebirthStore:SetAsync(player.UserId, rebirths)
	end)
end

Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local WalkSpeedValue = Instance.new("NumberValue")
	WalkSpeedValue.Name = "WalkSpeed"
	WalkSpeedValue.Parent = leaderstats

	local Cash = Instance.new("NumberValue")
	Cash.Name = "Cash"
	Cash.Value = loadCash(player)
	Cash.Parent = leaderstats

	local Rebirths = Instance.new("IntValue")
	Rebirths.Name = "Rebirths"
	Rebirths.Value = loadRebirths(player)
	Rebirths.Parent = leaderstats

	local storedSpeed, lastLogout = loadSpeed(player)
	local now = os.time()
	local offlineTime = now - lastLogout

	local inGroup = false
	pcall(function()
		inGroup = player:IsInGroup(GROUP_ID)
	end)

	local offlineGain = offlineTime * OFFLINE_INCREMENT * (inGroup and 2 or 1)
	local adjustedOfflineGain = applyDiminishingReturn(storedSpeed, offlineGain)
	storedSpeed = storedSpeed + adjustedOfflineGain

	WalkSpeedValue.Value = storedSpeed
	offlineGainValue.Value = math.max(0, adjustedOfflineGain)

	spawn(function()
		while player.Parent do
			task.wait(1)
			local isInGroup = false
			pcall(function()
				isInGroup = player:IsInGroup(GROUP_ID)
			end)

			local gain = isInGroup and INCREMENT_GROUP or INCREMENT_NON_GROUP
			if WalkSpeedValue.Value < MAX_SPEED then
				local adjustedGain = applyDiminishingReturn(WalkSpeedValue.Value, gain)
				WalkSpeedValue.Value += adjustedGain
			end
		end
	end)
end)

rebirthEvent.OnServerEvent:Connect(function(player)
	local stats = player:FindFirstChild("leaderstats")
	if not stats then return end

	local cash = stats:FindFirstChild("Cash")
	local rebirths = stats:FindFirstChild("Rebirths")
	if not cash or not rebirths then return end

	local nextCost = BASE_REBIRTH_COST * (rebirths.Value + 1)
	if cash.Value >= nextCost then
		cash.Value = 0
		rebirths.Value += 1

		local multiplier = rebirths.Value + 1
		local existing = player:FindFirstChild("CashMultiplier")
		if not existing then
			local multi = Instance.new("IntValue")
			multi.Name = "CashMultiplier"
			multi.Value = multiplier
			multi.Parent = player
		else
			existing.Value = multiplier
		end

		rebirthEvent:FireClient(player, {
			rebirths = rebirths.Value,
			nextCost = BASE_REBIRTH_COST * (rebirths.Value + 1),
			multiplier = multiplier
		})
	else
		rebirthEvent:FireClient(player, { error = "Not enough cash!" })
	end
end)

Players.PlayerRemoving:Connect(function(player)
	local leaderstats = player:FindFirstChild("leaderstats")
	if leaderstats then
		local WalkSpeedValue = leaderstats:FindFirstChild("WalkSpeed")
		local Cash = leaderstats:FindFirstChild("Cash")
		local Rebirths = leaderstats:FindFirstChild("Rebirths")
		if WalkSpeedValue then
			saveSpeed(player, WalkSpeedValue.Value)
		end
		if Cash then
			saveCash(player, Cash.Value)
		end
		if Rebirths then
			saveRebirths(player, Rebirths.Value)
		end
	end
end)

game:BindToClose(function()
	for _, player in pairs(Players:GetPlayers()) do
		local leaderstats = player:FindFirstChild("leaderstats")
		if leaderstats then
			local WalkSpeedValue = leaderstats:FindFirstChild("WalkSpeed")
			local Cash = leaderstats:FindFirstChild("Cash")
			local Rebirths = leaderstats:FindFirstChild("Rebirths")
			if WalkSpeedValue then
				saveSpeed(player, WalkSpeedValue.Value)
			end
			if Cash then
				saveCash(player, Cash.Value)
			end
			if Rebirths then
				saveRebirths(player, Rebirths.Value)
			end
		end
	end
end)
fix this or make it more stable at least