local v=require((game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")):WaitForChild("\078\101\118\101\114\109\111\114\101"))local E=v("\102\097\115\116\083\112\097\119\110")local F=v("\077\097\105\100")local N=v("\083\105\103\110\097\108")local Q=v("\086\097\108\117\101\079\098\106\101\099\116")local c={}c.ClassName="\072\117\109\097\110\111\105\100\084\114\097\099\107\101\114"c.__index=c function c.new(v)local l=setmetatable({},c)l._player=v or error("\078\111 \112\108\097\121\101\114")l._maid=F.new()l.Humanoid=Q.new()l._maid:GiveTask(l.Humanoid)l.AliveHumanoid=Q.new()l._maid:GiveTask(l.AliveHumanoid)l._maid:GiveTask(l.Humanoid.Changed:Connect(function(v,E,F)l:_handleHumanoidChanged(v,E,F)end))l._maid:GiveTask(l._player.CharacterAdded:Connect(function(v)l:_handleCharacter(v)end))if l._player.Character then E(l._handleCharacter,l,l._player.Character)end l.HumanoidDied=N.new()l._maid:GiveTask(l.HumanoidDied)return l end function c._handleCharacter(E,v)local N=F.new()E._maid._characterMaid=N local Q=v:FindFirstChildOfClass("\072\117\109\097\110\111\105\100")if Q then E.Humanoid.Value=Q return end E.Humanoid.Value=nil N._childAdded=v.ChildAdded:Connect(function(v)if v:IsA("\072\117\109\097\110\111\105\100")then N._childAdded=nil E.Humanoid.Value=v end end)end function c._handleHumanoidChanged(N,v,E,F)if not v then N.AliveHumanoid.Value=nil return end if v.Health<=0 then N.AliveHumanoid.Value=nil return end N.AliveHumanoid.Value=v F:GiveTask(v.Died:Connect(function()N.AliveHumanoid.Value=nil N.HumanoidDied:Fire(v)end))end function c.Destroy(v)v._maid:DoCleaning()setmetatable(v,nil)end return c
--- Tracks a player's character's humanoid
-- @classmod HumanoidTracker
-- @author Quenty

local require = require(game:GetService("ReplicatedStorage"):WaitForChild("Nevermore"))

local fastSpawn = require("fastSpawn")
local Maid = require("Maid")
local Signal = require("Signal")
local ValueObject = require("ValueObject")

local HumanoidTracker = {}
HumanoidTracker.ClassName = "HumanoidTracker"
HumanoidTracker.__index = HumanoidTracker

function HumanoidTracker.new(player)
	local self = setmetatable({}, HumanoidTracker)

	self._player = player or error("No player")
	self._maid = Maid.new()

	--- Tracks the current character humanoid, may be nil
	self.Humanoid = ValueObject.new()
	self._maid:GiveTask(self.Humanoid)

	--- Tracks the alive humanoid, may be nil
	self.AliveHumanoid = ValueObject.new()
	self._maid:GiveTask(self.AliveHumanoid)

	self._maid:GiveTask(self.Humanoid.Changed:Connect(function(newHumanoid, oldHumanoid, maid)
		self:_handleHumanoidChanged(newHumanoid, oldHumanoid, maid)
	end))

	self._maid:GiveTask(self._player.CharacterAdded:Connect(function(character)
		self:_handleCharacter(character)
	end))

	if self._player.Character then
		fastSpawn(self._handleCharacter, self, self._player.Character)
	end

	self.HumanoidDied = Signal.new()
	self._maid:GiveTask(self.HumanoidDied)

	return self
end

function HumanoidTracker:_handleCharacter(character)
	local maid = Maid.new()
	self._maid._characterMaid = maid

	local humanoid = character:FindFirstChildOfClass("Humanoid")
	if humanoid then
		self.Humanoid.Value = humanoid
		return
	end

	self.Humanoid.Value = nil

	-- Listen for changes
	maid._childAdded = character.ChildAdded:Connect(function(child)
		if child:IsA("Humanoid") then
			maid._childAdded = nil
			self.Humanoid.Value = child
		end
	end)
end

function HumanoidTracker:_handleHumanoidChanged(newHumanoid, oldHumanoid, maid)
	if not newHumanoid then
		self.AliveHumanoid.Value = nil
		return
	end

	if newHumanoid.Health <= 0 then
		self.AliveHumanoid.Value = nil
		return
	end

	self.AliveHumanoid.Value = newHumanoid

	maid:GiveTask(newHumanoid.Died:Connect(function()
		self.AliveHumanoid.Value = nil
		self.HumanoidDied:Fire(newHumanoid)
	end))
end

function HumanoidTracker:Destroy()
	self._maid:DoCleaning()
	setmetatable(self, nil)
end

return HumanoidTracker