local g=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 C=g("\084\105\109\101\083\121\110\099\077\097\110\097\103\101\114")local Q={}Q.ClassName="\080\114\111\106\101\099\116\105\108\101\080\104\121\115\105\099\115"function Q.new(g)g=g or 0 local D=setmetatable({},Q)rawset(D,"\095\112\111\115\105\116\105\111\110\048",g)rawset(D,"\095\118\101\108\111\099\105\116\121\048",0*g)rawset(D,"\095\097\099\099\101\108\101\114\097\116\105\111\110",0*g)rawset(D,"\095\116\105\109\101\048",C:GetTime())return D end function Q.Impulse(C,g)C.Velocity=C.Velocity+g end function Q.TimeSkip(Q,g)local D=C:GetTime()local q,S=Q:_positionVelocity(D+g)rawset(Q,"\095\112\111\115\105\116\105\111\110\048",q)rawset(Q,"\095\118\101\108\111\099\105\116\121\048",S)rawset(Q,"\095\116\105\109\101\048",D)end function Q.SetData(q,g,C,Q,D)rawset(q,"\095\116\105\109\101\048",g)rawset(q,"\095\112\111\115\105\116\105\111\110\048",C)rawset(q,"\095\118\101\108\111\099\105\116\121\048",Q)rawset(q,"\095\097\099\099\101\108\101\114\097\116\105\111\110",D)end function Q.__index(D,g)local q=C:GetTime()if Q[g]then return Q[g]elseif g=="\080\111\115\105\116\105\111\110"then local g,C=D:_positionVelocity(q)return g elseif g=="\086\101\108\111\099\105\116\121"then local g,C=D:_positionVelocity(q)return C elseif g=="\065\099\099\101\108\101\114\097\116\105\111\110"then return rawget(D,"\095\097\099\099\101\108\101\114\097\116\105\111\110")elseif g=="\083\116\097\114\116\084\105\109\101"then return rawget(D,"\095\116\105\109\101\048")elseif g=="\083\116\097\114\116\080\111\115\105\116\105\111\110"then return rawget(D,"\095\112\111\115\105\116\105\111\110\048")elseif g=="\083\116\097\114\116\086\101\108\111\099\105\116\121"then return rawget(D,"\095\118\101\108\111\099\105\116\121\048")elseif g=="\065\103\101"then return C:GetTime()-rawget(D,"\095\116\105\109\101\048")else error(("\037\113 \105\115 \110\111\116 \097 \118\097\108\105\100 \109\101\109\098\101\114 \111\102 \080\114\111\106\101\099\116\105\108\101\080\104\121\115\105\099\115"):format(tostring(g)),2)end end function Q.__newindex(D,g,Q)local q=C:GetTime()if g=="\080\111\115\105\116\105\111\110"then local g,C=D:_positionVelocity(q)rawset(D,"\095\112\111\115\105\116\105\111\110\048",Q)rawset(D,"\095\118\101\108\111\099\105\116\121\048",C)elseif g=="\086\101\108\111\099\105\116\121"then local g,C=D:_positionVelocity(q)rawset(D,"\095\112\111\115\105\116\105\111\110\048",g)rawset(D,"\095\118\101\108\111\099\105\116\121\048",Q)elseif g=="\065\099\099\101\108\101\114\097\116\105\111\110"then local g,C=D:_positionVelocity(q)rawset(D,"\095\112\111\115\105\116\105\111\110\048",g)rawset(D,"\095\118\101\108\111\099\105\116\121\048",C)rawset(D,"\095\097\099\099\101\108\101\114\097\116\105\111\110",Q)else error(("\037\113 \105\115 \110\111\116 \097 \118\097\108\105\100 \109\101\109\098\101\114 \111\102 \080\114\111\106\101\099\116\105\108\101\080\104\121\115\105\099\115"):format(tostring(g)),2)end rawset(D,"\095\116\105\109\101\048",q)end function Q._positionVelocity(C,g)local Q=g-rawget(C,"\095\116\105\109\101\048")local D=rawget(C,"\095\097\099\099\101\108\101\114\097\116\105\111\110")local q=rawget(C,"\095\118\101\108\111\099\105\116\121\048")local S=rawget(C,"\095\112\111\115\105\116\105\111\110\048")return(S+q*Q)+((.5*Q)*Q)*D,q+D*Q end return Q
--- Projectile physics used to syncronize state
-- @classmod ProjectilePhysics

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

local TimeSyncManager = require("TimeSyncManager")

local ProjectilePhysics = {}
ProjectilePhysics.ClassName = "ProjectilePhysics"

function ProjectilePhysics.new(initial)
	initial = initial or 0

	local self = setmetatable({}, ProjectilePhysics)

	rawset(self, "_position0", initial)
	rawset(self, "_velocity0", 0*initial)
	rawset(self, "_acceleration", 0*initial)
	rawset(self, "_time0", TimeSyncManager:GetTime())

	return self
end

function ProjectilePhysics:Impulse(velocity)
	self.Velocity = self.Velocity + velocity
end

function ProjectilePhysics:TimeSkip(delta)
	local time = TimeSyncManager:GetTime()
	local position, velocity = self:_positionVelocity(time+delta)
	rawset(self, "_position0", position)
	rawset(self, "_velocity0", velocity)
	rawset(self, "_time0", time)
end

function ProjectilePhysics:SetData(startTime, position0, velocity0, acceleration)
	rawset(self, "_time0", startTime)
	rawset(self, "_position0", position0)
	rawset(self, "_velocity0", velocity0)
	rawset(self, "_acceleration", acceleration)
end

function ProjectilePhysics:__index(index)
	local time = TimeSyncManager:GetTime()

	if ProjectilePhysics[index] then
		return ProjectilePhysics[index]
	elseif index == "Position" then
		local position, _ = self:_positionVelocity(time)
		return position
	elseif index == "Velocity" then
		local _, velocity = self:_positionVelocity(time)
		return velocity
	elseif index == "Acceleration" then
		return rawget(self, "_acceleration")
	elseif index == "StartTime" then
		return rawget(self, "_time0")
	elseif index == "StartPosition" then
		return rawget(self, "_position0")
	elseif index == "StartVelocity" then
		return rawget(self, "_velocity0")
	elseif index == "Age" then
		return TimeSyncManager:GetTime() - rawget(self, "_time0")
	else
		error(("%q is not a valid member of ProjectilePhysics"):format(tostring(index)), 2)
	end
end

function ProjectilePhysics:__newindex(index, value)
	local time = TimeSyncManager:GetTime()
	if index == "Position" then
		local _, velocity = self:_positionVelocity(time)
		rawset(self, "_position0", value)
		rawset(self, "_velocity0", velocity)
	elseif index == "Velocity" then
		local position, _ = self:_positionVelocity(time)
		rawset(self, "_position0", position)
		rawset(self, "_velocity0", value)
	elseif index == "Acceleration" then
		local position, velocity = self:_positionVelocity(time)
		rawset(self, "_position0", position)
		rawset(self, "_velocity0", velocity)
		rawset(self, "_acceleration", value)
	else
		error(("%q is not a valid member of ProjectilePhysics"):format(tostring(index)), 2)
	end
	rawset(self, "_time0", time)
end

function ProjectilePhysics:_positionVelocity(time)
	local dt = time - rawget(self, "_time0")
	local a0 = rawget(self, "_acceleration")
	local v0 = rawget(self, "_velocity0")
	local p0 = rawget(self, "_position0")
	return p0 + v0*dt + 0.5*dt*dt*a0,
	       v0 + a0*dt
end

return ProjectilePhysics
