PrefabFiles = {
	"boatlip_common",
	"boat_common",
	"waveyjones" --overwrite the old one completly
}

--- Improve Steering Animation ----
local function SteerInDir(self, dir_x, dir_z)
	-- if you are on a boat and the target heading is close enough to the current heading, don't do a steer. 
	local dontsteer = false
	local rx, rz = 0, 0
	if self.boat ~= nil then
		self.boat.components.boatphysics:SetTargetRudderDirection(dir_x, dir_z)

		local tx,tz = self.boat.components.boatphysics:GetTargetRudderDirection()

		rx,rz = self.boat.components.boatphysics:GetRudderDirection()
		local TOLLERANCE = 0.1

		if math.abs(tx - rx)<TOLLERANCE and math.abs(tz - rz)<TOLLERANCE then
			dontsteer = true
		end
	end
	if not dontsteer then
		self.should_play_left_turn_anim = (rz * dir_x - rx * dir_z) > 0
		self.inst:PushEvent("set_heading")
	end
end

local function replace_player(inst)
	if inst.components.steeringwheeluser ~= nil then
		inst.components.steeringwheeluser.SteerInDir = SteerInDir
	end
end

AddPlayerPostInit(replace_player)

--- Tune cookie cutter for new shape ---
local function replace_cookie(inst)
	if GLOBAL.TheWorld.ismastersim then
    	inst:SetBrain(require("brains/cookiecutterbrain"))
	end
end

AddPrefabPostInit("cookiecutter", replace_cookie)

--- Improve collision ----

local function replace_physics(inst)
	GLOBAL.MakeInventoryPhysics(inst)
    inst.Physics:CollidesWith(GLOBAL.COLLISION.ITEMS)
end
AddPrefabPostInit("boatfragment03", replace_physics)
AddPrefabPostInit("boatfragment04", replace_physics)
AddPrefabPostInit("boatfragment05", replace_physics)
AddPrefabPostInit("bullkelp_plant", replace_physics)

--- Boat loot---
local function SpawnFragment(lp, prefix, offset_x, offset_y, offset_z, ignite)
    local fragment = GLOBAL.SpawnPrefab(prefix)
    fragment.Transform:SetPosition(lp.x + offset_x, lp.y + offset_y, lp.z + offset_z)

    if offset_y > 0 then
        local physics = fragment.Physics
        if physics ~= nil then
            physics:SetVel(0, -0.25, 0)
        end
    end

	if ignite then
		fragment.components.burnable:Ignite()
	end

	return fragment
end

local function getrandompoint(inst)
	local x, z, c = nil, nil, 0
	local bx, by, bz = inst.Transform:GetWorldPosition()
	while c < 50 and (x == nil or not inst:is_point_on_boat(bx + x, by, bz + z)) do
		local radius = GLOBAL.GetRandomMinMax(0, inst.components.hull:GetRadius())
		local angle = GLOBAL.GetRandomMinMax(0, 2 * GLOBAL.PI)
		x, z = radius * math.cos(angle), radius * math.sin(angle)
		c = c + 1
	end
	if not inst:is_point_on_boat(bx + x, by, bz + z) then	
		x, z = 0, 0 
	end
	return x, z
end

local popping = GLOBAL.State
    {
        name = "popping",
        onenter = function(inst)
            local fx_boat_crackle = GLOBAL.SpawnPrefab("fx_boat_pop")
            fx_boat_crackle.Transform:SetPosition(inst.Transform:GetWorldPosition())
            inst.SoundEmitter:PlaySoundWithParams("turnoftides/common/together/boat/damage", {intensity= 1})
            inst.SoundEmitter:PlaySoundWithParams("turnoftides/common/together/boat/sink")

            local ignitefragments = inst.activefires > 0
            local locus_point = GLOBAL.Vector3(inst.Transform:GetWorldPosition())

			for prefab, number in pairs(inst.loot) do
				for i = 1, number do
					local x, z = getrandompoint(inst)
					SpawnFragment(locus_point, prefab, x, 0, z, ignitefragments)				
				end
			end
            inst:Remove()
        end,
    }
AddStategraphState("boat", popping)

--- Map Util for new shapes ----
GLOBAL.require "components/map"

local WALKABLE_PLATFORM_TAGS = {"walkableplatform"}
function GLOBAL.Map:GetPlatformAtPoint(pos_x, pos_y, pos_z, extra_radius)
	if pos_z == nil then
		pos_z = pos_y
		pos_y = 0
	end
    local entities = GLOBAL.TheSim:FindEntities(pos_x, pos_y, pos_z, TUNING.MAX_WALKABLE_PLATFORM_RADIUS, WALKABLE_PLATFORM_TAGS)
    for i, v in ipairs(entities) do
		if v.is_point_on_boat ~= nil then
			if v:is_point_on_boat(pos_x, pos_y, pos_z) then
				return v
			end
		else
			if math.sqrt(v:GetDistanceSqToPoint(pos_x, 0, pos_z)) <= TUNING.MAX_WALKABLE_PLATFORM_RADIUS + (extra_radius or 0) then
				return v
			end
		end
    end
    return nil
end

function GLOBAL.Map:IsPassableAtPointWithPlatformRadiusBias(x, y, z, allow_water, exclude_boats, platform_radius_bias, ignore_land_overhang)
	local valid_tile = self:IsAboveGroundAtPoint(x, y, z, allow_water) or ((not ignore_land_overhang) and self:IsVisualGroundAtPoint(x,y,z) or false)
    if not allow_water and not valid_tile then
        if not exclude_boats then
            local entities = GLOBAL.TheSim:FindEntities(x, 0, z, TUNING.MAX_WALKABLE_PLATFORM_RADIUS + platform_radius_bias, WALKABLE_PLATFORM_TAGS)
            for i, v in ipairs(entities) do
                local walkable_platform = v.components.walkableplatform            
                if walkable_platform ~= nil then
					if v.is_point_on_boat ~= nil then
						return v:is_point_on_boat(x, y, z)
					else
		                local platform_x, platform_y, platform_z = v.Transform:GetWorldPosition()
		                local distance_sq = GLOBAL.VecUtil_LengthSq(x - platform_x, z - platform_z)
		                return distance_sq <= walkable_platform.radius * walkable_platform.radius
					end
                end
            end
        end
		return false
    end
	return valid_tile
end

local function newdeploy(act)	
	local act_pos = act:GetActionPoint()
    if act.invobject ~= nil and act.invobject.components.deployable ~= nil  then
		act.invobject.deploy_rotation = act.rotation  --the newline, to pass angle from client to master
		if act.invobject.components.deployable:CanDeploy(act_pos, nil, act.doer) then
		    local container = act.doer.components.inventory or act.doer.components.container
		    local obj = container ~= nil and container:RemoveItem(act.invobject) or nil
		    if obj ~= nil then
		        if obj.components.deployable:Deploy(act_pos, act.doer, act.rotation) then
		            return true
		        else
		            container:GiveItem(obj)
				end
            end
        end
    end
end

GLOBAL.ACTIONS["DEPLOY"].fn = newdeploy