PLUGIN.name = "Survival System"
PLUGIN.author = "ZeMysticalTaco"
PLUGIN.description = "A survival system consisting of hunger and thirst."

if SERVER then
	function PLUGIN:OnCharacterCreated(client, character)
		character:SetData("hunger", 100)
		character:SetData("thirst", 100)
	end

	function PLUGIN:PlayerLoadedCharacter(client, character)
		timer.Simple(0.25, function()
			client:SetLocalVar("hunger", character:GetData("hunger", 100))
			client:SetLocalVar("thirst", character:GetData("thirst", 100))
		end)
	end

	function PLUGIN:CharacterPreSave(character)
		local client = character:GetPlayer()

		if (IsValid(client)) then
			character:SetData("hunger", client:GetLocalVar("hunger", 0))
			character:SetData("thirst", client:GetLocalVar("thirst", 0))
		end
	end

	local playerMeta = FindMetaTable("Player")

	function playerMeta:SetHunger(amount)
		local char = self:GetCharacter()

		if (char) then
			amount = math.Clamp(amount, 0, 100)
			char:SetData("hunger", amount)
			self:SetLocalVar("hunger", amount)
		end
	end

	function playerMeta:SetThirst(amount)
		local char = self:GetCharacter()

		if (char) then
			amount = math.Clamp(amount, 0, 100)
			char:SetData("thirst", amount)
			self:SetLocalVar("thirst", amount)
		end
	end

	function playerMeta:TickThirst(amount)
		local char = self:GetCharacter()

		if (char) then
			char:SetData("thirst", char:GetData("thirst", 100) - amount)
			self:SetLocalVar("thirst", char:GetData("thirst", 100) - amount)

			if char:GetData("thirst", 100) < 0 then
				char:SetData("thirst", 0)
				self:SetLocalVar("thirst", 0)
			end
		end
	end

	function playerMeta:TickHunger(amount)
		local char = self:GetCharacter()

		if (char) then
			char:SetData("hunger", char:GetData("hunger", 100) - amount)
			self:SetLocalVar("hunger", char:GetData("hunger", 100) - amount)

			if char:GetData("hunger", 100) < 0 then
				char:SetData("hunger", 0)
				self:SetLocalVar("hunger", 0)
			end
		end
	end

	function PLUGIN:PlayerTick(ply)
		if not ply:Alive() then return end
		
		local char = ply:GetCharacter()
		if not char then return end
		
		if ply.IsAdminMode and ply:IsAdminMode() then return end
		
		if ply:GetNetVar("hungertick", 0) <= CurTime() then
			ply:SetNetVar("hungertick", 200 + CurTime())
			ply:TickHunger(1)
		end

		if ply:GetNetVar("thirsttick", 0) <= CurTime() then
			ply:SetNetVar("thirsttick", 300 + CurTime())
			ply:TickThirst(1)
		end
		
		if ply:GetNetVar("survivaldamage", 0) <= CurTime() then
			ply:SetNetVar("survivaldamage", 1 + CurTime())
			
			local hunger = ply:GetLocalVar("hunger", 100)
			local thirst = ply:GetLocalVar("thirst", 100)
			local damage = 0
			
			if hunger <= 0 and thirst <= 0 then
				damage = 2
			elseif hunger <= 0 or thirst <= 0 then
				damage = 1
			end
			
			if damage > 0 then
				local dmg = DamageInfo()
				dmg:SetDamage(damage)
				dmg:SetDamageType(DMG_GENERIC)
				dmg:SetAttacker(ply)
				dmg:SetInflictor(ply)
				ply:TakeDamageInfo(dmg)
			end
		end
	end
	
	function PLUGIN:PlayerDeath(ply)
		local char = ply:GetCharacter()
		if char then
			char:SetData("hunger", 20)
			char:SetData("thirst", 20)
			ply:SetLocalVar("hunger", 20)
			ply:SetLocalVar("thirst", 20)
		end
	end
end

local playerMeta = FindMetaTable("Player")

function playerMeta:GetHunger()
	local char = self:GetCharacter()

	if (char) then
		return char:GetData("hunger", 100)
	end
end

function playerMeta:GetThirst()
	local char = self:GetCharacter()

	if (char) then
		return char:GetData("thirst", 100)
	end
end

function PLUGIN:AdjustStaminaOffset(client, offset)
	local hunger = client:GetHunger() or 100
	local thirst = client:GetThirst() or 100
	local multiplier = 1

	if (hunger <= 0) or (thirst <= 0) then
		multiplier = 0.2
	elseif (hunger <= 30) or (thirst <= 30) then
		multiplier = 0.5
	elseif (hunger <= 60) or (thirst <= 60) then
		multiplier = 0.8
	end

	if (multiplier != 1) then
		if (offset > 0) then
			return offset * multiplier
		else
			return offset * (2 - multiplier)
		end
	end
end

ix.command.Add("charsetthirst", {
	adminOnly = true,
	arguments = {
		ix.type.string,
		ix.type.number,
	},
	OnRun = function(self, client, target, thirst)
		local target = ix.util.FindPlayer(target)
		local thirst = tonumber(thirst)

		if !target then
			client:Notify("Invalid Target!")
			return
		end
		target:SetThirst(thirst)

		if client == target then
            client:Notify("You have set your thrist to "..thirst)
        else
            client:Notify("You have set "..target:Name().."'s thirst to "..thirst)
            target:Notify(client:Name().." has set your thirst to "..thirst)
        end
	end
})

ix.command.Add("charsethunger", {
	adminOnly = true,
	arguments = {
		ix.type.string,
		ix.type.number,
	},
	OnRun = function(self, client, target, hunger)
		local target = ix.util.FindPlayer(target)
		local hunger = tonumber(hunger)

		if !target then
			client:Notify("Invalid Target!")
			return
		end

		target:SetHunger(hunger)

		if client == target then
            client:Notify("You have set your hunger to "..hunger)
        else
            client:Notify("You have set "..target:Name().."'s hunger to "..hunger)
            target:Notify(client:Name().." has set your hunger to "..hunger)
        end
	end
})
