wait(1)local g={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 V(g,V,S)assert(g~=nil,"\080\097\114\101\110\116 \105\115 \110\105\108")assert(type(V)=="\115\116\114\105\110\103","\078\097\109\101 \105\115 \110\111\116 \097 \115\116\114\105\110\103\046")local I=g:FindFirstChild(V)local J=tick()local R=false while not I and g do wait(0)I=g:FindFirstChild(V)if not R and J+(S or 5)<=tick()then R=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"..(g:GetFullName()..("\044 "..(V.."\041"))))if S then return g:FindFirstChild(V)end end end if not g then warn("\080\097\114\101\110\116 \098\101\099\097\109\101 \110\105\108\046")end return I end local function S(g,V)for V,S in next,V do if type(V)=="\110\117\109\098\101\114"then S.Parent=g else g[V]=S end end return g end local function I(g,V)return S(Instance.new(g),V)end local J={}function J.new()local g={}local V=Instance.new("\066\105\110\100\097\098\108\101\069\118\101\110\116")local S=nil local I=nil function g.fire(g,...)S={...}I=select("\035",...)V:Fire()end function g.connect(J,g)if not g then error("\099\111\110\110\101\099\116\040\110\105\108\041",2)end return V.Event:connect(function()g(unpack(S,1,I))end)end function g.wait(g)V.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,I)end return g end local function R(g,V,S,J)S=S or"\087\101\108\100"local R=I(S,{Part0=g,Part1=V;C0=CFrame.new();C1=V.CFrame:toObjectSpace(g.CFrame);Parent=J or g})return R end local function s(g,V,S,I)for g,I in pairs(g)do R(V,I,S,V)end if not I then for g,V in pairs(g)do V.Anchored=false end V.Anchored=false end end local function j(g,V)V(g)for g,S in next,g:GetChildren()do j(S,V)end end local function X(g)local V={}j(g,function(g)if g:IsA("\066\097\115\101\080\097\114\116")then V[#V+1]=g end end)return V end local function l(g,V)local S={}j(g,function(g)if g:IsA("\066\097\115\101\080\097\114\116")and not V(g)then S[#S+1]=g end end)return S end local function m(g)local V=g local S=Players:GetPlayerFromCharacter(V)while not S do if V.Parent then V=V.Parent S=Players:GetPlayerFromCharacter(V)else return nil end end return V,S end local D do local g={GiveTask=function(g,V)local S=#g.Tasks+1 g.Tasks[S]=V return S end,DoCleaning=function(g)local V=g.Tasks for g,S in pairs(V)do if type(S)=="\102\117\110\099\116\105\111\110"then S()else S:disconnect()end V[g]=nil end end}local V={__index=function(V,S)if g[S]then return g[S]else return V.Tasks[S]end end;__newindex=function(g,V,S)local I=g.Tasks if S==nil then if type(I[V])~="\102\117\110\099\116\105\111\110"then I[V]:disconnect()end elseif I[V]then g[V]=nil end I[V]=S end}function D()return setmetatable({Tasks={},Instances={}},V)end end local function H(g)return g and g:IsA("\080\108\097\121\101\114")end local function i(g)if H(g)then local V=g.Character if V then return V.Parent and(V:FindFirstChild("\072\117\109\097\110\111\105\100")and(V:FindFirstChild("\072\117\109\097\110\111\105\100\082\111\111\116\080\097\114\116")and(V:FindFirstChild("\084\111\114\115\111")and(V:FindFirstChild("\072\101\097\100")and(V.Humanoid:IsA("\072\117\109\097\110\111\105\100")and(V.Head:IsA("\066\097\115\101\080\097\114\116")and(V.Torso:IsA("\066\097\115\101\080\097\114\116")and true)))))))end else print("\091\067\104\101\099\107\067\104\097\114\097\099\116\101\114\093 - \067\104\097\114\097\099\116\101\114 \067\104\101\099\107 \102\097\105\108\101\100\033")end return nil end local function h(g)local V=0 local S=Vector3.new(0,0,0)for g,I in pairs(g)do V=V+I:GetMass()S=S+I:GetMass()*I.Position end return S/V,V 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("Torso") 
				and Character:FindFirstChild("Head") 
				and Character.Humanoid:IsA("Humanoid")
				and Character.Head:IsA("BasePart")
				and Character.Torso: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
