local F=require(((game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")):WaitForChild("\087\111\114\108\100\069\110\103\105\110\101")):WaitForChild("\073\109\112\111\114\116"))local t=F("\116")local l=F("\116\097\098\108\101")local B=F("\046\046\047\069\110\116\105\116\121")local A=t.numberMin(0)local U=t.tuple(t.optional(A))local v=B:Extend("\067\104\097\114\097\099\116\101\114\069\110\116\105\116\121",{abstract=true})function v.constructor(t,F)assert(U(F))B:super(t)t._health=F or 100 t._maxHealth=F or 100 t._stats={}end function v.GetHealth(F)return F._health end function v.SetStat(B,F,l)assert((t.tuple(t.string,t.numberMin(0)))(F,l))B._stats[F]=l end function v.GetStats(F)return l.copy(F._stats)end function v.SetStats(l,F)assert((t.map(t.string,t.numberPositive))(F))for F,B in next,F do assert(t.numberPositive(B))assert(t.string(F))l._stats[F]=B end end function v.GetStat(t,F)return t._stats[F]or 0 end function v.SetHealth(t,F)assert(A(F))t._health=F t._maxHealth=F end function v.TakeDamage(t,F)assert(A(F))if F>t._health then t._health=0 else t._health=t._health-F end end function v.Heal(t,F)assert(A(F))if t._health+F>t._maxHealth then t._health=t._maxHealth else t._health=t._health+F end end function v.IsAlive(F)return F._health>0 end return v
local import = require(game:GetService("ReplicatedStorage"):WaitForChild("WorldEngine"):WaitForChild("Import"))

local t = import "t"
local table = import "table"
local Entity = import "../Entity"

local unsignedFloat = t.numberMin(0)
local CharacterEntityConstructorArgs = t.tuple(t.optional(unsignedFloat))

local CharacterEntity = Entity:Extend("CharacterEntity", {abstract = true})
function CharacterEntity:constructor(health)
	assert(CharacterEntityConstructorArgs(health))
	Entity:super(self)

	self._health = health or 100
	self._maxHealth = health or 100
	self._stats = {}
end

function CharacterEntity:GetHealth()
	return self._health
end

function CharacterEntity:SetStat(name, value)
	assert(t.tuple(t.string, t.numberMin(0))(name, value))
	self._stats[name] = value
end

function CharacterEntity:GetStats()
	return table.copy(self._stats)
end

function CharacterEntity:SetStats(stats)
	assert(t.map(t.string, t.numberPositive)(stats))

	for stat, value in next, stats do
		assert(t.numberPositive(value))
		assert(t.string(stat))
		self._stats[stat] = value
	end
end

function CharacterEntity:GetStat(name)
	return self._stats[name] or 0
end

function CharacterEntity:SetHealth(health)
	assert(unsignedFloat(health))
	self._health = health
	self._maxHealth = health
end

function CharacterEntity:TakeDamage(amount)
	assert(unsignedFloat(amount))

	if amount > self._health then
		self._health = 0
	else
		self._health = self._health - amount
	end
end

function CharacterEntity:Heal(amount)
	assert(unsignedFloat(amount))

	if self._health + amount > self._maxHealth then
		self._health = self._maxHealth
	else
		self._health = self._health + amount
	end
end

function CharacterEntity:IsAlive()
	return self._health > 0
end

return CharacterEntity
