local A=game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")local p=A:WaitForChild("\077\111\100\117\108\101\115")local f=require(p.src.utils.Logger)local R=require(p.src.GhostAbility)local u=require(p.src.objects.InventoryObjects)local K=u.PET_TYPES local d=A:WaitForChild("\077\111\100\101\108\115")local i={}i.__index=i local g="\112\101\116"function i.create(R,A,p,f)local u={variableName=g..("\095"..A.id),slot=f,petObject=A;petName=A.name;character=p,started=true}setmetatable(u,i)return u end function i.init(A)A.petModel=A:addToCharacter()R:setGhostCollisionGroup(A.petModel)A:start(A.petModel)if A.petObject.ability==K.TRAIL then A:addTrailToCharacter()end end function i.removeCurrentPet(A)local p=A.character:FindFirstChild(A.variableName)if p then p:Destroy()end if A.petObject.ability==K.TRAIL then A:removeTrailFromCharacter()end end function i.delete(A)f:d("\082\101\109\111\118\105\110\103 \112\101\116 ",A.petName)A.started=false A:removeCurrentPet()end function i.addToCharacter(A)if not A.character then f:w("\078\111\115\101\108\102\046\099\104\097\114\097\099\116\101\114 \116\111 \097\100\100 \112\101\116 \116\111")return end local p=d.Pets[A.petName]:Clone()if p==nil then f:w("\078\111 \080\101\116")return end p.Name=A.variableName p.Parent=A.character return p end function i.start(p,A)f:d("\073\110\105\116 \112\101\116\077\111\100\101\108")for A,p in pairs(A:GetChildren())do if p.ClassName=="\080\097\114\116"or p.ClassName=="\087\101\100\103\101\080\097\114\116"or p.ClassName=="\084\114\117\115\115\080\097\114\116"or p.ClassName=="\067\111\114\110\101\114\087\101\100\103\101\080\097\114\116"or p.ClassName=="\077\101\115\104\080\097\114\116"then p.Anchored=false p.CanCollide=false end end spawn(function()p:animate()end)end local function S(A,p)return Vector3.new(math.cos(math.rad(p))*A,0,math.sin(math.rad(p))*A)end function i.animate(A)local p=.5 local R=.025 local u=false local K=0 local d=A.petModel.PrimaryPart d.BodyGyro.MaxTorque=Vector3.new(4000000,4000000,4000000)d.BodyPosition.P=100000 local i=A.character local g=i:FindFirstChild("\072\101\097\100")local T=i:FindFirstChild("\072\117\109\097\110\111\105\100")while A.started do if not u then K=K+R if K>=p then u=true end else K=K-R if K<=-p then u=false end end if d~=nil and(T~=nil and g~=nil)then if T.Health>=0 then local p=g.CFrame*CFrame.new(0,-0.5+K,0)local f=360/A.slot local R=S(5,f)d.BodyPosition.Position=Vector3.new(p.x,p.y,p.z)+R d.BodyGyro.CFrame=g.CFrame*CFrame.new(3,0,-3)else f:i("\072\117\109\097\110 \100\105\101\100")end end wait()end end function i.addTrailToCharacter(A)local p=A.petObject.trailModelName f:w("\065\100\100 \116\114\097\105\108 "..(A.petObject.trailModelName.." \116\111 \099\104\097\114\097\099\116\101\114\046"))local R=d.Trails[p]:Clone()local u=R:Clone()local K=A.character u.Name=p u.Parent=K.HumanoidRootPart if A.character:FindFirstChild("\085\112\112\101\114\084\111\114\115\111")then u.Attachment0=K.Head.FaceFrontAttachment u.Attachment1=K.UpperTorso.WaistRigAttachment else u.Attachment0=K.Head.FaceFrontAttachment u.Attachment1=K.Torso.WaistBackAttachment end end function i.removeTrailFromCharacter(A)local p=A.character.HumanoidRootPart:FindFirstChild(A.petObject.trailModelName)if p then p:Destroy()end end return i
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local Modules = ReplicatedStorage:WaitForChild('Modules')
local logger = require(Modules.src.utils.Logger)
local GhostAbility = require(Modules.src.GhostAbility)
local InventoryObjects = require(Modules.src.objects.InventoryObjects)
local PET_TYPES = InventoryObjects.PET_TYPES
local Models = ReplicatedStorage:WaitForChild('Models')

local Pet = {}

Pet.__index = Pet

local PET_ATTRIBUTE = 'pet'

function Pet:create(petObject, character, slot)
	local this = {
		variableName = PET_ATTRIBUTE .. '_' .. petObject.id,
		slot = slot,
		petObject = petObject,
		petName = petObject.name,
		character = character,
		started = true,
	}

	setmetatable(this, Pet)
	return this
end

function Pet:init()
	self.petModel = self:addToCharacter()
	GhostAbility:setGhostCollisionGroup(self.petModel)
	self:start(self.petModel)

	if self.petObject.ability == PET_TYPES.TRAIL then
		self:addTrailToCharacter()
	end
end

function Pet:removeCurrentPet()
	local petModel = self.character:FindFirstChild(self.variableName)
	if petModel then
		petModel:Destroy()
	end
	if self.petObject.ability == PET_TYPES.TRAIL then
		self:removeTrailFromCharacter()
	end
end

function Pet:delete()
	logger:d('Removing pet ', self.petName)
	self.started = false

	self:removeCurrentPet()
end

function Pet:addToCharacter()
	if not self.character then
		logger:w('Noself.character to add pet to')
		return
	end

	-- self:removeCurrentPet()

	local petModel = Models.Pets[self.petName]:Clone()

	if petModel == nil then
		logger:w('No Pet')
		return
	end

	petModel.Name = self.variableName
	petModel.Parent = self.character

	return petModel
end

function Pet:start(petModel)
	logger:d('Init petModel')

	for i, v in pairs(petModel:GetChildren()) do
		if v.ClassName == 'Part' or v.ClassName == 'WedgePart' or v.ClassName == 'TrussPart' or v.ClassName == 'CornerWedgePart' or v.ClassName == 'MeshPart' then
			v.Anchored = false
			v.CanCollide = false
		end
	end

	spawn(function()
		self:animate()
	end)
end

-- local RotationOffset = 360/#ducks
local function GetPointOnCircle(CircleRadius, Degrees)
	return Vector3.new(
		math.cos(math.rad(Degrees)) * CircleRadius,
		0,
		math.sin(math.rad(Degrees)) * CircleRadius
	)
end

function Pet:animate()
	local maxFloat = 0.5
	local floatInc = 0.025
	local sw = false
	local fl = 0

	local part = self.petModel.PrimaryPart
	part.BodyGyro.MaxTorque = Vector3.new(4000000, 4000000, 4000000)
	part.BodyPosition.P = 100000

	local character = self.character
	local head = character:FindFirstChild('Head')
	local humanoid = character:FindFirstChild('Humanoid')

	while self.started do
		if not sw then
			fl = fl + floatInc
			if fl >= maxFloat then
				sw = true
			end
		else
			fl = fl - floatInc
			if fl <= -maxFloat then
				sw = false
			end
		end
		if part ~= nil and humanoid ~= nil and head ~= nil then
			if humanoid.Health >= 0 then
				local cf = head.CFrame * CFrame.new(0, -0.5 + fl, 0)

				local rotationOffset = 360 / self.slot
				local circlePoint = GetPointOnCircle(5, rotationOffset)

				part.BodyPosition.Position = Vector3.new(cf.x, cf.y, cf.z) + circlePoint

				part.BodyGyro.CFrame = head.CFrame * CFrame.new(3, 0, -3)
				--break
			else
				logger:i('Human died')
			end
		end
		wait()
	end
end

function Pet:addTrailToCharacter()
	local name = self.petObject.trailModelName
	logger:w('Add trail ' .. self.petObject.trailModelName .. ' to character.')
	local trail = Models.Trails[name]:Clone()
	local plrTrail = trail:Clone()

	local character = self.character
	plrTrail.Name = name
	plrTrail.Parent = character.HumanoidRootPart

	if self.character:FindFirstChild('UpperTorso') then
		plrTrail.Attachment0 = character.Head.FaceFrontAttachment
		plrTrail.Attachment1 = character.UpperTorso.WaistRigAttachment
	else
		plrTrail.Attachment0 = character.Head.FaceFrontAttachment
		plrTrail.Attachment1 = character.Torso.WaistBackAttachment
	end
end

function Pet:removeTrailFromCharacter()
	local trail = self.character.HumanoidRootPart:FindFirstChild(self.petObject.trailModelName)
	if trail then
		trail:Destroy()
	end
end

return Pet