GLOBALS_LUA = true

-- general
DEBUG_MODE = false

-- colision categories
category_body  = 1    -- bike geoms
category_tire  = 2
category_skid  = 4
category_rider = 8
category_bike  = category_body + category_tire + 
                 category_skid + category_rider

category_rail  = 16   -- world geoms
category_obst  = 32
category_grnd  = 64
category_haz   = 128
category_world = category_rail + category_obst +
                 category_grnd + category_haz

category_pwrup = 256
category_srfc  = 512
category_trig  = 1024
category_aitag = 2048

category_all   = category_bike + category_world
category_none  = 0


-- position and rate of primary bike in scene
scenepos  = 0
scenerate = 0
chasetarg = 1

-- layers for stacking transparent sprites on the ground
surface_layer = 0.02
powerup_layer = 0.02
shadow_layer  = 0.04

-- snowmobiles
mob    = {}

-- global sounds
sounds = {}
sounds.menu_select = E.load_sound("data/sounds/menu_select.ogg")
sounds.menu_click  = E.load_sound("data/sounds/menu_click3.ogg")
sounds.wipeout     = E.load_sound("data/sounds/wipeout2.ogg")
sounds.lap         = E.load_sound("data/sounds/lap.ogg")
sounds.rdyset      = E.load_sound("data/sounds/rdyset.ogg")
sounds.go          = E.load_sound("data/sounds/go.ogg")
sounds.overheat    = E.load_sound("data/sounds/alarm2.ogg")
sounds.boost       = E.load_sound("data/sounds/boost.ogg")
sounds.chill       = E.load_sound("data/sounds/chill.ogg")
sounds.finish      = nil
sounds.menu_music  = E.load_sound("data/sounds/christmasbeat.ogg")
sounds.race_music  = E.load_sound("data/sounds/christmasbeatfull.ogg")

E.set_sound_amplitude(sounds.overheat, 0.5)

-- digit and alpha map code taken from Bob Kooima's Electro example file
-- asteroids.lua.  See www.evl.uic.edu/rlk/electro

digit_map = {
    [0] = { 0.00, 0.25, 0.75, 1.00 },
    [1] = { 0.25, 0.50, 0.75, 1.00 },
    [2] = { 0.50, 0.75, 0.75, 1.00 },
    [3] = { 0.75, 1.00, 0.75, 1.00 },
    [4] = { 0.00, 0.25, 0.50, 0.75 },
    [5] = { 0.25, 0.50, 0.50, 0.75 },
    [6] = { 0.50, 0.75, 0.50, 0.75 },
    [7] = { 0.75, 1.00, 0.50, 0.75 },
    [8] = { 0.00, 0.25, 0.25, 0.50 },
    [9] = { 0.25, 0.50, 0.25, 0.50 }
}

alpha_map = {
    ["A"] = { 0.000, 0.125, 0.75, 1.00 },
    ["B"] = { 0.125, 0.250, 0.75, 1.00 },
    ["C"] = { 0.250, 0.375, 0.75, 1.00 },
    ["D"] = { 0.375, 0.500, 0.75, 1.00 },
    ["E"] = { 0.500, 0.625, 0.75, 1.00 },
    ["F"] = { 0.625, 0.750, 0.75, 1.00 },
    ["G"] = { 0.750, 0.875, 0.75, 1.00 },
    ["H"] = { 0.875, 1.000, 0.75, 1.00 },
    ["I"] = { 0.000, 0.125, 0.50, 0.75 },
    ["J"] = { 0.125, 0.250, 0.50, 0.75 },
    ["K"] = { 0.250, 0.375, 0.50, 0.75 },
    ["L"] = { 0.375, 0.500, 0.50, 0.75 },
    ["M"] = { 0.500, 0.625, 0.50, 0.75 },
    ["N"] = { 0.625, 0.750, 0.50, 0.75 },
    ["O"] = { 0.750, 0.875, 0.50, 0.75 },
    ["P"] = { 0.875, 1.000, 0.50, 0.75 },
    ["Q"] = { 0.000, 0.125, 0.25, 0.50 },
    ["R"] = { 0.125, 0.250, 0.25, 0.50 },
    ["S"] = { 0.250, 0.375, 0.25, 0.50 },
    ["T"] = { 0.375, 0.500, 0.25, 0.50 },
    ["U"] = { 0.500, 0.625, 0.25, 0.50 },
    ["V"] = { 0.625, 0.750, 0.25, 0.50 },
    ["W"] = { 0.750, 0.875, 0.25, 0.50 },
    ["X"] = { 0.875, 1.000, 0.25, 0.50 },
    ["Y"] = { 0.000, 0.125, 0.00, 0.25 },
    ["Z"] = { 0.125, 0.250, 0.00, 0.25 },
    [":"] = { 0.250, 0.375, 0.00, 0.25 },
    ["_"] = { 0.375, 0.500, 0.00, 0.25 },
}

-- functions

function next_letter(letter)
    local byte = string.byte(letter)

    if byte >= 90 then
        return "A"
    else
        return string.char(byte + 1)
    end
end

function prev_letter(letter)
    local byte = string.byte(letter)

    if byte <= 65 then
        return "Z"
    else
        return string.char(byte - 1)
    end
end

function set_digit_sprite(sprite, n)
    E.set_sprite_range(sprite, digit_map[n][1],
                               digit_map[n][2],
                               digit_map[n][3],
                               digit_map[n][4])
end

function set_alpha_sprite(sprite, c)
     E.set_sprite_range(sprite, alpha_map[c][1],
                               alpha_map[c][2],
                               alpha_map[c][3],
                               alpha_map[c][4])
end

function make_init_sprite( inits, scale )
    local isp = {}

    isp.pivot = E.create_pivot()

    local s = {}
    s[1] = string.sub(inits, 1, 1)
    s[2] = string.sub(inits, 2, 2)
    s[3] = string.sub(inits, 3, 3)

    for i = 1, 3 do
        isp[i] = make_sprite("data/alpha.png", true, true)
	set_alpha_sprite     (isp[i], s[i])
	E.set_entity_scale   (isp[i], 0.125, 0.25, 1)
        E.set_entity_position(isp[i], (i-1)*128, 0, 0)
	E.parent_entity      (isp[i], isp.pivot)
    end

    isp.str = inits
    
    E.set_entity_scale(isp.pivot, scale/128, scale/128, 1)

    return isp
end

function set_init_sprite( isp, c, i )

    local s = {}
    s[1] = string.sub(isp.str, 1, 1)
    s[2] = string.sub(isp.str, 2, 2)
    s[3] = string.sub(isp.str, 3, 3)

    s[i] = c

    isp.str = s[1]..s[2]..s[3]

    set_alpha_sprite(isp[i], c)
    
end

function make_time_sprite( time, scale )
    local tsp = {}

    tsp.pivot = E.create_pivot()
    tsp.time  = time

    local d = {}
    d[1] = math.mod(math.floor(time               / 600), 10)
    d[2] = math.mod(math.floor(time               / 60 ), 10)
    d[3] = math.mod(math.floor(math.mod(time, 60) / 10 ), 10)
    d[4] = math.mod(math.floor(time                    ), 10)
    d[5] = math.mod(math.floor(time               * 10 ), 10)
    d[6] = math.mod(math.floor(time               * 100), 10)

    local tspc = 105
    for i = 1, 6 do
        tsp[i] = make_sprite("data/digits.png", true, true)
	set_digit_sprite(tsp[i], d[i])
	if i < 3 then
	    E.set_entity_scale   (tsp[i], 0.25, 0.25, 1)
	    E.set_entity_position(tsp[i], (i-1)*tspc, 0, 0)
	elseif i < 5 then
	    E.set_entity_scale   (tsp[i], 0.25, 0.25, 1)
	    E.set_entity_position(tsp[i], tspc/4 + (i-1)*tspc, 0, 0)
	else
	    E.set_entity_scale   (tsp[i], (0.25)/1.25, (0.25)/1.25, 1)
	    E.set_entity_position(tsp[i], 4.1*tspc + (i-5)*tspc/1.25,64-64*4/5, 0)
	end
	E.parent_entity(tsp[i], tsp.pivot)
    end
    
    tsp[7] = make_sprite("data/alpha.png", true, true)
    set_alpha_sprite     (tsp[7], ":")
    E.set_entity_scale   (tsp[7], 0.125, 0.25, 1)
    E.set_entity_position(tsp[7], 1.625*tspc, 0, 0)
    E.parent_entity      (tsp[7], tsp.pivot)

    E.set_entity_scale(tsp.pivot, scale/128, scale/128, 1)
    return tsp
end

function set_time_sprite( tsp, time )
    local d = {}
    d[1] = math.mod(math.floor(time               / 600), 10)
    d[2] = math.mod(math.floor(time               / 60 ), 10)
    d[3] = math.mod(math.floor(math.mod(time, 60) / 10 ), 10)
    d[4] = math.mod(math.floor(time                    ), 10)
    d[5] = math.mod(math.floor(time               * 10 ), 10)
    d[6] = math.mod(math.floor(time               * 100), 10)

    for i = 1, 6 do
	set_digit_sprite(tsp[i], d[i])
    end

    tsp.time = time
end

function make_sprite(filename, trans, unlit )
    local image = E.create_image(filename)
    local brush = E.create_brush()

    E.set_brush_flags(brush, E.brush_flag_transparent, trans)
    E.set_brush_flags(brush, E.brush_flag_unlit,       unlit)

    E.set_brush_color(brush, 1.0, 1.0, 1.0, 1.0)
    E.set_brush_image(brush, image)

    return E.create_sprite(brush)
end

function format_time( time )
    -- time: a floating point number of seconds

    local msecs = math.mod(math.floor(time * 100), 100)
    if msecs < 10 then msecs = "0"..string.format("%d", msecs) 
    else msecs = string.format("%d", msecs) end

    local secs  = math.mod(time, 60)
    if secs < 10 then secs = "0"..string.format("%d", secs) 
    else secs = string.format("%d", secs) end

    local mins  = math.floor(time / 60) 
    if mins < 10 then mins = "0"..string.format("%d", mins) 
    else mins = string.format("%d", mins) end

    return mins .. ":" .. secs .. "." .. msecs

end

function parse_time( timestr )
    -- timestr: a string of the format "mins:secs.msecs"
     
    local i0, i1, mins, secs, msecs = string.find(timestr, "(%d+):(%d+).(%d+)")
 
    return mins * 60 + secs + msecs / 100
end


function check_flag ( value, flag )
    if not flag or (flag == 0) then return false end
    return math.mod( math.floor(value / flag), 2) == 1
end


-- expects: xyz : values to convert
--          n   : new coord system
--                {xx, xy, xz, yx, yy, yz, zx, zy, zz}
function convert_coord( x, y, z, n )

    local px = n[1] * x + n[4] * y + n[7] * z
    local py = n[2] * x + n[5] * y + n[8] * z
    local pz = n[3] * x + n[6] * y + n[9] * z

    return px, py, pz
end

function get_vectors( pivot )
    local xx, xy, xz = E.get_entity_x_vector(pivot)
    local yx, yy, yz = E.get_entity_y_vector(pivot)
    local zx, zy, zz = E.get_entity_z_vector(pivot)

    return {xx, xy, xz, yx, yy, yz, zx, zy, zz}
end

function pos_distance( x1, y1, z1, x2, y2, z2 )
    local dx, dy, dz = x2-x1 , y2-y1 , z2-z1
    local dsq        = dx*dx + dy*dy + dz*dz
    return math.sqrt(dsq)
end