wait(1)local Z={MaxSpeed=30;Acceleration=5,MaxRotationCorrectionAcceleration=math.pi/40,PercentExtraCargo=.005;TurnAccelerationFactor=150,MaxTurnSpeed=2.5,MaxShipTiltInRadians=math.pi/8;TiltRatioFactor=.01,AmplitudeOfWaves=2.5,MaxShipYawInRadians=math.pi/120;AddedYawOnSpeed=math.pi/80,WaterLevel=39}local function x(Z,x,s)assert(Z~=nil,"\080\097\114\101\110\116 \105\115 \110\105\108")assert(type(x)=="\115\116\114\105\110\103","\078\097\109\101 \105\115 \110\111\116 \097 \115\116\114\105\110\103\046")local F=Z:FindFirstChild(x)local i=tick()local o=false while not F and Z do wait(0)F=Z:FindFirstChild(x)if not o and i+(s or 5)<=tick()then o=true warn("\073\110\102\105\110\105\116\101 \121\105\101\108\100 \112\111\115\115\105\098\108\101 \102\111\114 \087\097\105\116\070\111\114\067\104\105\108\100\040"..(Z:GetFullName()..("\044 "..(x.."\041"))))if s then return Z:FindFirstChild(x)end end end if not Z then warn("\080\097\114\101\110\116 \098\101\099\097\109\101 \110\105\108\046")end return F end local function s(Z,x)for x,s in next,x do if type(x)=="\110\117\109\098\101\114"then s.Parent=Z else Z[x]=s end end return Z end local function F(Z,x)return s(Instance.new(Z),x)end local i={}function i.new()local Z={}local x=Instance.new("\066\105\110\100\097\098\108\101\069\118\101\110\116")local s=nil local F=nil function Z.fire(Z,...)s={...}F=select("\035",...)x:Fire()end function Z.connect(i,Z)if not Z then error("\099\111\110\110\101\099\116\040\110\105\108\041",2)end return x.Event:connect(function()Z(unpack(s,1,F))end)end function Z.wait(Z)x.Event:wait()assert(s,"\077\105\115\115\105\110\103 \097\114\103 \100\097\116\097\044 \108\105\107\101\108\121 \100\117\101 \116\111 \058\084\119\101\101\110\083\105\122\101\047\080\111\115\105\116\105\111\110 \099\111\114\114\117\112\116\105\110\103 \116\104\114\101\097\100\114\101\102\115\046")return unpack(s,1,F)end return Z end local function o(Z,x,s,i)s=s or"\087\101\108\100"local o=F(s,{Part0=Z,Part1=x;C0=CFrame.new();C1=x.CFrame:toObjectSpace(Z.CFrame);Parent=i or Z})return o end local function L(Z,x,s,F)for Z,F in pairs(Z)do o(x,F,s,x)end if not F then for Z,x in pairs(Z)do x.Anchored=false end x.Anchored=false end end local function G(Z,x)x(Z)for Z,s in next,Z:GetChildren()do G(s,x)end end local function C(Z)local x={}G(Z,function(Z)if Z:IsA("\066\097\115\101\080\097\114\116")then x[#x+1]=Z end end)return x end local function m(Z,x)local s={}G(Z,function(Z)if Z:IsA("\066\097\115\101\080\097\114\116")and not x(Z)then s[#s+1]=Z end end)return s end local function Y(Z)local x=Z local s=Players:GetPlayerFromCharacter(x)while not s do if x.Parent then x=x.Parent s=Players:GetPlayerFromCharacter(x)else return nil end end return x,s end local g do local Z={GiveTask=function(Z,x)local s=#Z.Tasks+1 Z.Tasks[s]=x return s end,DoCleaning=function(Z)local x=Z.Tasks for Z,s in pairs(x)do if type(s)=="\102\117\110\099\116\105\111\110"then s()else s:disconnect()end x[Z]=nil end end}local x={__index=function(x,s)if Z[s]then return Z[s]else return x.Tasks[s]end end;__newindex=function(Z,x,s)local F=Z.Tasks if s==nil then if type(F[x])~="\102\117\110\099\116\105\111\110"then F[x]:disconnect()end elseif F[x]then Z[x]=nil end F[x]=s end}function g()return setmetatable({Tasks={},Instances={}},x)end end local function j(Z)return Z and Z:IsA("\080\108\097\121\101\114")end local function c(Z)if j(Z)then local x=Z.Character if x then return x.Parent and(x:FindFirstChild("\072\117\109\097\110\111\105\100")and(x:FindFirstChild("\072\117\109\097\110\111\105\100\082\111\111\116\080\097\114\116")and(x:FindFirstChild("\072\101\097\100")and(x.Humanoid:IsA("\072\117\109\097\110\111\105\100")and(x.Head:IsA("\066\097\115\101\080\097\114\116")and(x.HumanoidRootPart:IsA("\066\097\115\101\080\097\114\116")and true))))))end else end return nil end local function y(Z)local x=0 local s=Vector3.new(0,0,0)for Z,F in pairs(Z)do x=x+F:GetMass()s=s+F:GetMass()*F.Position end return s/x,x end

wait(1)

local Configuration = {
	MaxSpeed               = 30;
	Acceleration           = 5; -- Will always be a little bit less than this because ROBLOX characters will add mass. Also, friction.
	MaxRotationCorrectionAcceleration = math.pi/40;  -- I wouldn't touch this. 
		-- math.pi/10 -- Correct for 18 degrees every.... second?
	PercentExtraCargo      = 0.005; -- Compared to boat's mass (weight), how much extra cargo can it support (irncludes characters) before it starts sinking. 
	
	TurnAccelerationFactor = 150; -- E_e No idea why this is 500.
	MaxTurnSpeed           = 2.5; -- RotVelocity will probably never get to this. 
	
	MaxShipTiltInRadians   = math.pi/8;
	TiltRatioFactor        = 0.01; -- Don't touch this. Used because the BodyAngularVelocity "can't even" when it comes to reaching desired velocity. 

	AmplitudeOfWaves       = 2.5; -- How far up/down the boat moves in the waves.  (Amplitude, so if you physics, you realize it can move this magnitude away from the starting point, either up, or down).
	MaxShipYawInRadians    = math.pi/120; -- Yaws in the waves
	AddedYawOnSpeed        = math.pi/80;
	
	WaterLevel = 39;
}

local function WaitForChild(Parent, Name, TimeLimit)
	-- Waits for a child to appear. Not efficient, but it shoudln't have to be. It helps with debugging. 
	-- Useful when ROBLOX lags out, and doesn't replicate quickly.
	-- @param TimeLimit If TimeLimit is given, then it will return after the timelimit, even if it hasn't found the child.

	assert(Parent ~= nil, "Parent is nil")
	assert(type(Name) == "string", "Name is not a string.")

	local Child     = Parent:FindFirstChild(Name)
	local StartTime = tick()
	local Warned    = false

	while not Child and Parent do
		wait(0)
		Child = Parent:FindFirstChild(Name)
		if not Warned and StartTime + (TimeLimit or 5) <= tick() then
			Warned = true
			warn("Infinite yield possible for WaitForChild(" .. Parent:GetFullName() .. ", " .. Name .. ")")
			if TimeLimit then
				return Parent:FindFirstChild(Name)
			end
		end
	end

	if not Parent then
		warn("Parent became nil.")
	end

	return Child
end


local function Modify(Instance, Values)
	-- Modifies an Instance by using a table.  

	for Index, Value in next, Values do
		if type(Index) == "number" then
			Value.Parent = Instance
		else
			Instance[Index] = Value
		end
	end
	return Instance
end

local function Make(ClassType, Properties)
	-- Using a syntax hack to create a nice way to Make new items.  

	return Modify(Instance.new(ClassType), Properties)
end

local Signal = {}

function Signal.new()
	local sig = {}
	
	local mSignaler = Instance.new('BindableEvent')
	
	local mArgData = nil
	local mArgDataCount = nil
	
	function sig:fire(...)
		mArgData = {...}
		mArgDataCount = select('#', ...)
		mSignaler:Fire()
	end
	
	function sig:connect(f)
		if not f then error("connect(nil)", 2) end
		return mSignaler.Event:connect(function()
			f(unpack(mArgData, 1, mArgDataCount))
		end)
	end
	
	function sig:wait()
		mSignaler.Event:wait()
		assert(mArgData, "Missing arg data, likely due to :TweenSize/Position corrupting threadrefs.")
		return unpack(mArgData, 1, mArgDataCount)
	end
	
	return sig
end


local function WeldTogether(Part0, Part1, JointType, WeldParent)
	--- Weld's 2 parts together
	-- @param Part0 The first part
	-- @param Part1 The second part (Dependent part most of the time).
	-- @param [JointType] The type of joint. Defaults to weld.
	-- @param [WeldParent] Parent of the weld, Defaults to Part0 (so GC is better).
	-- @return The weld created.

	JointType = JointType or "Weld"

	local NewWeld = Make(JointType, {
		Part0  = Part0;
		Part1  = Part1;
		C0     = CFrame.new();--Part0.CFrame:inverse();
		C1     = Part1.CFrame:toObjectSpace(Part0.CFrame); --Part1.CFrame:inverse() * Part0.CFrame;-- Part1.CFrame:inverse();
		Parent = WeldParent or Part0;
	})

	return NewWeld
end

local function WeldParts(Parts, MainPart, JointType, DoNotUnanchor)
	-- @param Parts The Parts to weld. Should be anchored to prevent really horrible results.
	-- @param MainPart The part to weld the model to (can be in the model).
	-- @param [JointType] The type of joint. Defaults to weld. 
	-- @parm DoNotUnanchor Boolean, if true, will not unachor the model after cmopletion.

	for _, Part in pairs(Parts) do
		WeldTogether(MainPart, Part, JointType, MainPart)
	end

	if not DoNotUnanchor then
		for _, Part in pairs(Parts) do
			Part.Anchored = false
		end
		MainPart.Anchored = false
	end
end

local function CallOnChildren(Instance, FunctionToCall)
	-- Calls a function on each of the children of a certain object, using recursion.  

	FunctionToCall(Instance)

	for _, Child in next, Instance:GetChildren() do
		CallOnChildren(Child, FunctionToCall)
	end
end

local function GetBricks(StartInstance)
	local List = {}

	-- if StartInstance:IsA("BasePart") then
	-- 	List[#List+1] = StartInstance
	-- end

	CallOnChildren(StartInstance, function(Item)
		if Item:IsA("BasePart") then
			List[#List+1] = Item;
		end
	end)

	return List;
end

local function GetBricksWithIgnoreFunction(StartInstance, DoIgnore)
	--- Get's the bricks in a model, but will not get a brick that is "NoInclude"

	local List = {}

	CallOnChildren(StartInstance, function(Item)
		if Item:IsA("BasePart") and not DoIgnore(Item) then
			List[#List+1] = Item
		end
	end)

	return List
end


local function GetCharacter(Descendant)
	-- Returns the Player and Charater that a descendent is part of, if it is part of one.
	-- @param Descendant A child of the potential character. 

	local Charater = Descendant
	local Player   = Players:GetPlayerFromCharacter(Charater)

	while not Player do
		if Charater.Parent then
			Charater = Charater.Parent
			Player   = Players:GetPlayerFromCharacter(Charater)
		else
			return nil
		end
	end

	return Charater, Player
end

local MakeMaid do
	local index = {
		GiveTask = function(self,task)
			local n = #self.Tasks+1
			self.Tasks[n] = task
			return n
		end;
		DoCleaning = function(self)
			local tasks = self.Tasks
			for name,task in pairs(tasks) do
				if type(task) == 'function' then
					task()
				else
					task:disconnect()
				end
				tasks[name] = nil
			end
			-- self.Tasks = {}
		end;
	};
	local mt = {
		__index = function(self,k)
			if index[k] then
				return index[k]
			else
				return self.Tasks[k]
			end
		end;
		__newindex = function(self,k,v)
			local tasks = self.Tasks
			if v == nil then
				-- disconnect if the task is an event
				if type(tasks[k]) ~= 'function' then
					tasks[k]:disconnect()
				end
			elseif tasks[k] then
				-- clear previous task
				self[k] = nil
			end
			tasks[k] = v
		end;
	}
	
	function MakeMaid()
		return setmetatable({Tasks={},Instances={}},mt)
	end
end


local function CheckPlayer(Player)
	--- Makes sure a player has all necessary components.
	-- @return Boolean If the player has all the right components

	return Player and Player:IsA("Player") 
end

local function CheckCharacter(Player)
	-- Makes sure a character has all the right "parts"
	
	if CheckPlayer(Player) then
		local Character = Player.Character;

		if Character then
			
			return Character.Parent
				and Character:FindFirstChild("Humanoid")
				and Character:FindFirstChild("HumanoidRootPart")
				and Character:FindFirstChild("Head") 
				and Character.Humanoid:IsA("Humanoid")
				and Character.Head:IsA("BasePart")
				and Character.HumanoidRootPart:IsA("BasePart")
				and true
		end
	else
		--print("[CheckCharacter] - Character Check failed!")
	end

	return nil
end

local function GetCenterOfMass(Parts)
	--- Return's the world vector center of mass.
	-- Lots of help from Hippalectryon :D

	local TotalMass = 0
	local SumOfMasses = Vector3.new(0, 0, 0)

	for _, Part in pairs(Parts) do
		-- Part.BrickColor = BrickColor.new("Bright yellow")
		TotalMass = TotalMass + Part:GetMass()
		SumOfMasses = SumOfMasses + Part:GetMass() * Part.Position
	end

	-- print("Sum of masses: " .. tostring(SumOfMasses))
	-- print("Total mass:    " .. tostring(TotalMass))

	return SumOfMasses/TotalMass, TotalMass
end
