#Conditional Hooks
$Application: FS2_Open

$On Game Init:

[

TerrainObjects = {}

function SoftAlignToY(ship, strength, threshold)

    if type(strength) ~= "number" then
        ba.warning("strength must be a number!!!!!!!!!!!!!!!!!!")
        return
    end

    if type(threshold) ~= "number" then
        ba.warning("threshold must be a number!!!!!!!!!!!!!!!!!!")
        return
    end

    if mn.Ships[ship]:isValid() then    --always check validity of game objects!

        local thisShip = mn.Ships[ship]             --Good form is to declare internal local objects
        local globalUp = ba.createVector(0,1,0)
        local localUp = thisShip.Orientation:rotateVector(globalUp)
        local angle = math.atan2(localUp.x, localUp.y)
        local thresholdRadians = (threshold * (math.pi / 180))
        --ba.print(tostring(localUp) .. "\n")
        --ba.print(tostring(angle) .. "\n")

        if math.abs(angle) > thresholdRadians then
            angle = (angle > 0 and (angle - thresholdRadians)) or (angle + thresholdRadians)

            local rotation = ba.createOrientation(0, -angle, 0)
            thisShip.Orientation = thisShip.Orientation * rotation

            local newVelocity = thisShip.Physics.RotationalVelocity
            newVelocity.z = 0
            thisShip.Physics.RotationalVelocity = newVelocity
        else
            local newVelocity = thisShip.Physics.RotationalVelocity
            newVelocity.z = newVelocity.z - (angle * strength * ba.getFrametime())
            thisShip.Physics.RotationalVelocity = newVelocity
        end
    end

end

function PitchCap(ship, threshold, lowerThreshold)

    if type(threshold) ~= "number" then
        ba.warning("threshold must be a number!!!!!!!!!!!!!!!!!!")
        return
    end

    if mn.Ships[ship]:isValid() then    --always check validity of game objects!

        local thisShip = mn.Ships[ship]             --Good form is to declare internal local objects
        local globalUp = ba.createVector(0,1,0)
        local fvec = thisShip.Orientation:getFvec()
        local angle = math.asin(fvec:getDotProduct(globalUp))

        if lowerThreshold == nil then
            local thresholdRadians = (threshold * (math.pi / 180))
            if math.abs(angle) > thresholdRadians then
                angle = (angle > 0 and (angle - thresholdRadians)) or (angle + thresholdRadians)
                local axis = globalUp:getCrossProduct(fvec):getNormalized()
                local angle2 = math.atan2(axis.z, axis.x)
                local rotation = ba.createOrientation(0, 0, -angle2) * ba.createOrientation(angle, 0, 0) * ba.createOrientation(0, 0, angle2)
                thisShip.Orientation = rotation * thisShip.Orientation
            end
        else
            local lowerThresholdRad = (lowerThreshold * (math.pi / 180))
            local upperThresholdRad = (threshold * (math.pi / 180))
            if angle > upperThresholdRad or angle < lowerThresholdRad then
                angle = angle - (angle > upperThresholdRad and upperThresholdRad or lowerThresholdRad)
                local axis = globalUp:getCrossProduct(fvec):getNormalized()
                local angle2 = math.atan2(axis.z, axis.x)
                local rotation = ba.createOrientation(0, 0, -angle2) * ba.createOrientation(angle, 0, 0) * ba.createOrientation(0, 0, angle2)
                thisShip.Orientation = rotation * thisShip.Orientation
            end
        end
    end

end

function HardAlignToY(shipStr, lockToY, shipObj)
    local ship

    if shipObj ~= nil then
        ship = shipObj
    else
        ship = mn.Ships[shipStr]
    end

    -- handle wings
    if ship == nil or not ship:isValid() then
        local wing = mn.Wings[shipStr]

        if wing == nil or not wing:isValid() then
            return
        end

        for i = 1, #wing do
            HardAlignToY("", lockToY, wing[i])
        end
        return
    end


    local globalUp = ba.createVector(0,1,0)
    local localUp = ship.Orientation:rotateVector(globalUp)
    local angle = math.atan2(localUp.x, localUp.y)
    local rotation = ba.createOrientation(0, -angle, 0)
    ship.Orientation = ship.Orientation * rotation

    local newVelocity = ship.Physics.RotationalVelocity
    newVelocity.z = 0
    ship.Physics.RotationalVelocity = newVelocity

    if lockToY ~= nil and lockToY == 1 then
        local fvec = ship:getfvec():projectOntoPlane(globalUp):getNormalized()
        ship.Orientation = ba.createOrientationFromVectors(fvec, ship:getuvec())
    end

end

YVel = 0

function addTerrainObj(terrainShip)
    local terrain = mn.Ships[terrainShip]
    if terrain ~= nil and terrain:isValid() then
        table.insert(TerrainObjects, terrain)
    end
end

function hover(hoverShipStr, height, rigidity, hoverShipObj)
    local hoverShip

    if hoverShipObj ~= nil then
        hoverShip = hoverShipObj
    else
        hoverShip = mn.Ships[hoverShipStr]
    end

    -- handle wings
    if hoverShip == nil or not hoverShip:isValid() then
        local hoveringWing = mn.Wings[hoverShipStr]

        if hoveringWing == nil or not hoveringWing:isValid() then
            return
        end

        for i = 1, #hoveringWing do
            hover("",height, rigidity, hoveringWing[i])
        end
        return
    end

    local pos = nil
    local cinfo = nil
    for i, terrain in ipairs(TerrainObjects) do
        local thisPos, thisCinfo = terrain:checkRayCollision(hoverShip.Position + ba.createVector(0,50,0), hoverShip.Position + ba.createVector(0,-1000,0))

        if thisPos ~= nil then
            if pos == nil or thisPos[2] > pos[2] then
                pos = thisPos
                cinfo = thisCinfo
            end
        end
    end

    if pos == nil then
        return
    end

    local restY = pos[2] + height
    local currentY = hoverShip.Position[2] - (hoverShip.Physics.Velocity[2] * ba.getMissionFrametime())

    if currentY < restY then
        rigidity = rigidity * 3
    end

    local newY = restY + (currentY - restY) * math.exp(-rigidity * ba.getMissionFrametime())

    local newPos = ba.createVector(hoverShip.Position[1], newY, hoverShip.Position[3])
    hoverShip.Position = newPos
end

]

$On Gameplay Start: [ GroundCameraActive = false ]

$State: GS_STATE_GAME_PLAY
$On Frame: [
    if GroundCameraActive then
        local cam = gr.getCurrentCamera(true)
        ba.print("\nchase? "..tostring(gr.hasViewmode(VM_CHASE)))
        ba.print("\nfreecam? "..tostring(gr.hasViewmode(VM_FREECAMERA)))
        ba.print("\nexternal? "..tostring(gr.hasViewmode(VM_EXTERNAL)))
        ba.print("\nother ship? "..tostring(gr.hasViewmode(VM_OTHER_SHIP)))
        if cam ~= nil and cam:isValid() and gr.hasViewmode(VM_CHASE) and not gr.hasViewmode(VM_FREECAMERA) and not gr.hasViewmode(VM_EXTERNAL) and not gr.hasViewmode(VM_OTHER_SHIP) then
            local pos = cam.Position
            local target = hv.Player.Position.y + 11
            pos.y = pos.y + (target - pos.y) * math.exp(-20 * ba.getMissionFrametime())
            cam.Position = pos
        end
    end
]

#End
