Lua loaded records #9
44
browser.lua
44
browser.lua
@ -1,15 +1,21 @@
|
|||||||
local leaderboard = nil
|
local MapRecords
|
||||||
local maps
|
local maps
|
||||||
local mapIndex = 1
|
local mapIndex = 1
|
||||||
local scrollPos = 1
|
local scrollPos = 1
|
||||||
local modes = nil
|
local modes = nil
|
||||||
local mode = 1
|
local mode = 1
|
||||||
local prefMode = nil
|
local prefMode = nil
|
||||||
|
local ModeSep
|
||||||
|
|
||||||
|
---- Imported functions ----
|
||||||
|
|
||||||
-- Imported functions -------
|
|
||||||
-- lb_common.lua
|
-- lb_common.lua
|
||||||
local ZoneAct = lb_ZoneAct
|
local ZoneAct = lb_ZoneAct
|
||||||
local TicsToTime = lb_TicsToTime
|
local TicsToTime = lb_TicsToTime
|
||||||
|
|
||||||
|
-- lb_store.lua
|
||||||
|
local GetMapRecords = lb_get_map_records
|
||||||
|
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
local cv_kartencore
|
local cv_kartencore
|
||||||
@ -25,10 +31,8 @@ end
|
|||||||
local function updateModes()
|
local function updateModes()
|
||||||
-- set available modes for this map
|
-- set available modes for this map
|
||||||
modes = {}
|
modes = {}
|
||||||
for mode, scoreTable in pairs(leaderboard) do
|
for mode, _ in pairs(MapRecords) do
|
||||||
if scoreTable[getMap()] then
|
table.insert(modes, mode)
|
||||||
table.insert(modes, mode)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
table.sort(modes)
|
table.sort(modes)
|
||||||
|
|
||||||
@ -46,6 +50,8 @@ local function updateMapIndex(n)
|
|||||||
mapIndex = mapIndexOffset(n)
|
mapIndex = mapIndexOffset(n)
|
||||||
scrollPos = 1
|
scrollPos = 1
|
||||||
|
|
||||||
|
MapRecords = GetMapRecords(maps[mapIndex], ModeSep)
|
||||||
|
|
||||||
updateModes()
|
updateModes()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -337,7 +343,7 @@ local function drawScore(v, i, pos, score, highlight)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function drawBrowser(v, player)
|
local function drawBrowser(v, player)
|
||||||
if not leaderboard then return end
|
if not MapRecords then return end
|
||||||
|
|
||||||
v.fadeScreen(0xFF00, 16)
|
v.fadeScreen(0xFF00, 16)
|
||||||
|
|
||||||
@ -358,23 +364,20 @@ local function drawBrowser(v, player)
|
|||||||
|
|
||||||
if not modes then return end
|
if not modes then return end
|
||||||
|
|
||||||
local gamemode = leaderboard[modes[mode]]
|
local records = MapRecords[modes[mode]]
|
||||||
if not gamemode then return end
|
if not records then return end
|
||||||
|
|
||||||
local scoreTable = gamemode[getMap()]
|
local record_count = #records
|
||||||
if not scoreTable then return end
|
scrollPos = max(min(scrollPos, record_count - 3), 1)
|
||||||
|
local endi = min(scrollPos + 7, record_count)
|
||||||
local scores = #scoreTable
|
|
||||||
scrollPos = max(min(scrollPos, scores - 3), 1)
|
|
||||||
local endi = min(scrollPos + 7, scores)
|
|
||||||
for i = scrollPos, endi do
|
for i = scrollPos, endi do
|
||||||
drawScore(v, i - scrollPos + 1, i, scoreTable[i], scoreTable[i].name == player.name)
|
drawScore(v, i - scrollPos + 1, i, records[i], records[i].name == player.name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
rawset(_G, "DrawBrowser", drawBrowser)
|
rawset(_G, "DrawBrowser", drawBrowser)
|
||||||
|
|
||||||
local function initBrowser(lb)
|
local function initBrowser(modeSep)
|
||||||
leaderboard = lb
|
ModeSep = modeSep
|
||||||
|
|
||||||
-- set mapIndex to current map
|
-- set mapIndex to current map
|
||||||
for i, m in ipairs(maps) do
|
for i, m in ipairs(maps) do
|
||||||
@ -384,6 +387,9 @@ local function initBrowser(lb)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- initialize MapRecords
|
||||||
|
MapRecords = GetMapRecords(gamemap, ModeSep)
|
||||||
|
|
||||||
scrollPos = 1
|
scrollPos = 1
|
||||||
updateModes()
|
updateModes()
|
||||||
end
|
end
|
||||||
@ -485,6 +491,6 @@ local function netvars(net)
|
|||||||
mode = net($)
|
mode = net($)
|
||||||
prefMode = net($)
|
prefMode = net($)
|
||||||
scrollPos = net($)
|
scrollPos = net($)
|
||||||
leaderboard = net($)
|
MapRecords = net($)
|
||||||
end
|
end
|
||||||
addHook("NetVars", netvars)
|
addHook("NetVars", netvars)
|
||||||
|
@ -24,3 +24,23 @@ rawset(_G, "lb_ZoneAct", function(map)
|
|||||||
|
|
||||||
return z
|
return z
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
rawset(_G, "lb_stat_t", function(speed, weight)
|
||||||
|
if speed and weight then
|
||||||
|
return (speed << 4) | weight
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
local F_SPBBIG = 0x4
|
||||||
|
local F_SPBEXP = 0x8
|
||||||
|
-- True if a is better than b
|
||||||
|
rawset(_G, "lb_comp", function(a, b)
|
||||||
|
-- Calculates the difficulty, harder has higher priority
|
||||||
|
-- if s is positive then a is harder
|
||||||
|
-- if s is negative then b is harder
|
||||||
|
-- if s is 0 then compare time
|
||||||
|
local s = (a.flags & (F_SPBEXP | F_SPBBIG)) - (b.flags & (F_SPBEXP | F_SPBBIG))
|
||||||
|
return s > 0 or not(s < 0 or a.time >= b.time)
|
||||||
|
end)
|
||||||
|
218
lb_store.lua
Normal file
218
lb_store.lua
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
-- This file handles the storage and related netvars of the leaderboard
|
||||||
|
|
||||||
|
---- Imported functions ----
|
||||||
|
|
||||||
|
-- lb_common.lua
|
||||||
|
local stat_t = lb_stat_t
|
||||||
|
local lbComp = lb_comp
|
||||||
|
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
local LEADERBOARD_FILE = "leaderboard.txt"
|
||||||
|
|
||||||
|
-- ColdStore are records loaded from lua addons
|
||||||
|
-- this table should never be modified outside of the AddColdStore function
|
||||||
|
local ColdStore = {}
|
||||||
|
|
||||||
|
-- Livestore are new records nad records loaded from leaderboard.txt file
|
||||||
|
local LiveStore = {}
|
||||||
|
|
||||||
|
|
||||||
|
-- GLOBAL
|
||||||
|
-- Function for adding records from lua
|
||||||
|
local function AddColdStore(record)
|
||||||
|
ColdStore[record.map] = $ or {}
|
||||||
|
table.insert(ColdStore[record.map], record)
|
||||||
|
end
|
||||||
|
rawset(_G, "lb_add_coldstore_record", AddColdStore)
|
||||||
|
|
||||||
|
|
||||||
|
-- Insert mode separated records from the flat sourceTable into dest
|
||||||
|
local function insertRecords(dest, sourceTable, modeSep)
|
||||||
|
if not sourceTable then return end
|
||||||
|
|
||||||
|
local mode = nil
|
||||||
|
for _, record in ipairs(sourceTable) do
|
||||||
|
mode = record.flags & modeSep
|
||||||
|
dest[mode] = $ or {}
|
||||||
|
table.insert(dest[mode], record)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- GLOBAL
|
||||||
|
-- Construct the leaderboard table of the supplied mapid
|
||||||
|
-- combines the ColdStore and LiveStore records
|
||||||
|
local function GetMapRecords(map, modeSep)
|
||||||
|
local mapRecords = {}
|
||||||
|
|
||||||
|
-- Insert ColdStore records
|
||||||
|
insertRecords(mapRecords, ColdStore[map], modeSep)
|
||||||
|
|
||||||
|
-- Insert LiveStore records
|
||||||
|
insertRecords(mapRecords, LiveStore[map], modeSep)
|
||||||
|
|
||||||
|
-- Sort records
|
||||||
|
for _, records in pairs(mapRecords) do
|
||||||
|
table.sort(records, lbComp)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Remove duplicate entries
|
||||||
|
for _, records in pairs(mapRecords) do
|
||||||
|
local players = {}
|
||||||
|
local i = 1
|
||||||
|
while i <= #records do
|
||||||
|
if players[records[i].name] then
|
||||||
|
table.remove(records, i)
|
||||||
|
else
|
||||||
|
players[records[i].name] = true
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return mapRecords
|
||||||
|
end
|
||||||
|
rawset(_G, "lb_get_map_records", GetMapRecords)
|
||||||
|
|
||||||
|
local function insertOrReplaceRecord(map, score, modeSep)
|
||||||
|
LiveStore[map] = $ or {}
|
||||||
|
|
||||||
|
for i, record in ipairs(LiveStore[map]) do
|
||||||
|
-- Replace the record
|
||||||
|
if record.name == score.name
|
||||||
|
and (record.flags & modeSep) == (score.flags & modeSep) then
|
||||||
|
LiveStore[map][i] = score
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(LiveStore[map], score)
|
||||||
|
|
||||||
|
-- TODO: remove excess records
|
||||||
|
end
|
||||||
|
|
||||||
|
local MSK_SPEED = 0xF0
|
||||||
|
local MSK_WEIGHT = 0xF
|
||||||
|
local function stat_str(stat)
|
||||||
|
if stat then
|
||||||
|
return string.format("%d%d", (stat & MSK_SPEED) >> 4, stat & MSK_WEIGHT)
|
||||||
|
end
|
||||||
|
|
||||||
|
return "0"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- GLOBAL
|
||||||
|
-- Save a record to the LiveStore and write to disk
|
||||||
|
-- SaveRecord will replace the record holders previous record but it will not compare any record times
|
||||||
|
local function SaveRecord(score, map, modeSep)
|
||||||
|
insertOrReplaceRecord(map, score, modeSep)
|
||||||
|
|
||||||
|
print("Saving score")
|
||||||
|
|
||||||
|
if not isserver then return end
|
||||||
|
|
||||||
|
local f = assert(
|
||||||
|
io.open(LEADERBOARD_FILE, "w"),
|
||||||
|
"Failed to open file for writing: "..LEADERBOARD_FILE
|
||||||
|
)
|
||||||
|
|
||||||
|
f:setvbuf("line")
|
||||||
|
|
||||||
|
for mapid, records in pairs(LiveStore) do
|
||||||
|
for _, record in ipairs(records) do
|
||||||
|
f:write(
|
||||||
|
mapid, "\t",
|
||||||
|
record.name, "\t",
|
||||||
|
record.skin, "\t",
|
||||||
|
record.color, "\t",
|
||||||
|
record.time, "\t",
|
||||||
|
table.concat(record.splits, " "), "\t",
|
||||||
|
record.flags, "\t",
|
||||||
|
stat_str(record.stat), "\n"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
rawset(_G, "lb_save_record", SaveRecord)
|
||||||
|
|
||||||
|
local function netvars(net)
|
||||||
|
LiveStore = net($)
|
||||||
|
end
|
||||||
|
|
||||||
|
addHook("NetVars", netvars)
|
||||||
|
|
||||||
|
local function score_t(map, name, skin, color, time, splits, flags, stat)
|
||||||
|
return {
|
||||||
|
["map"] = map,
|
||||||
|
["name"] = name,
|
||||||
|
["skin"] = skin,
|
||||||
|
["color"] = color,
|
||||||
|
["time"] = time,
|
||||||
|
["splits"] = splits,
|
||||||
|
["flags"] = flags,
|
||||||
|
["stat"] = stat
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local function parseScore(str)
|
||||||
|
-- Leaderboard is stored in the following tab separated format
|
||||||
|
-- mapnum, name, skin, color, time, splits, flags, stat
|
||||||
|
local t = {}
|
||||||
|
for word in (str.."\t"):gmatch("(.-)\t") do
|
||||||
|
table.insert(t, word)
|
||||||
|
end
|
||||||
|
|
||||||
|
local splits = {}
|
||||||
|
if t[6] != nil then
|
||||||
|
for str in t[6]:gmatch("([^ ]+)") do
|
||||||
|
table.insert(splits, tonumber(str))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local flags = 0
|
||||||
|
if t[7] != nil then
|
||||||
|
flags = tonumber(t[7])
|
||||||
|
end
|
||||||
|
|
||||||
|
local stats = nil
|
||||||
|
if t[8] != nil then
|
||||||
|
if #t[8] >= 2 then
|
||||||
|
local speed = tonumber(string.sub(t[8], 1, 1))
|
||||||
|
local weight = tonumber(string.sub(t[8], 2, 2))
|
||||||
|
stats = stat_t(speed, weight)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return score_t(
|
||||||
|
tonumber(t[1]), -- Map
|
||||||
|
t[2], -- Name
|
||||||
|
t[3], -- Skin
|
||||||
|
t[4], -- Color
|
||||||
|
tonumber(t[5]), -- Time
|
||||||
|
splits,
|
||||||
|
flags,
|
||||||
|
stats
|
||||||
|
)
|
||||||
|
end
|
||||||
|
rawset(_G, "lb_parse_score", parseScore)
|
||||||
|
|
||||||
|
-- Load the livestore
|
||||||
|
do
|
||||||
|
if isserver then
|
||||||
|
local f = assert(
|
||||||
|
io.open(LEADERBOARD_FILE, "r"),
|
||||||
|
"Failed to open file: "..LEADERBOARD_FILE
|
||||||
|
)
|
||||||
|
|
||||||
|
for l in f:lines() do
|
||||||
|
local score = parseScore(l)
|
||||||
|
print(score.name)
|
||||||
|
LiveStore[score.map] = $ or {}
|
||||||
|
table.insert(LiveStore[score.map], score)
|
||||||
|
end
|
||||||
|
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
end
|
274
leaderboard.lua
274
leaderboard.lua
@ -1,9 +1,8 @@
|
|||||||
-- Leaderboards written by Not
|
-- Leaderboards written by Not
|
||||||
-- Reusable
|
-- Reusable
|
||||||
|
|
||||||
-- Leaderboard Table
|
-- Holds the current maps records table including all modes
|
||||||
-- [mode][mapnum][scoreTable]
|
local MapRecords = {}
|
||||||
local lb = {}
|
|
||||||
|
|
||||||
local timeFinished = 0
|
local timeFinished = 0
|
||||||
local disable = false
|
local disable = false
|
||||||
@ -12,7 +11,7 @@ local splits = {}
|
|||||||
local PATCH = nil
|
local PATCH = nil
|
||||||
local help = true
|
local help = true
|
||||||
local EncoreInitial = nil
|
local EncoreInitial = nil
|
||||||
local scoreTable
|
local ScoreTable
|
||||||
|
|
||||||
|
|
||||||
-- Text flash on finish
|
-- Text flash on finish
|
||||||
@ -94,11 +93,17 @@ local allowJoin
|
|||||||
-- lb_common.lua
|
-- lb_common.lua
|
||||||
local ticsToTime = lb_TicsToTime
|
local ticsToTime = lb_TicsToTime
|
||||||
local zoneAct = lb_ZoneAct
|
local zoneAct = lb_ZoneAct
|
||||||
|
local stat_t = lb_stat_t
|
||||||
|
local lbComp = lb_comp
|
||||||
|
|
||||||
-- browser.lua
|
-- browser.lua
|
||||||
local InitBrowser = InitBrowser
|
local InitBrowser = InitBrowser
|
||||||
local DrawBrowser = DrawBrowser
|
local DrawBrowser = DrawBrowser
|
||||||
local BrowserController = BrowserController
|
local BrowserController = BrowserController
|
||||||
|
|
||||||
|
-- lb_store.lua
|
||||||
|
local GetMapRecords = lb_get_map_records
|
||||||
|
local SaveRecord = lb_save_record
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
-- cvars
|
-- cvars
|
||||||
@ -164,79 +169,17 @@ local cv_interrupt = CV_RegisterVar({
|
|||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
local function setST(t, map, flags, scoreTable)
|
|
||||||
local mode = flags & ST_SEP
|
|
||||||
t[mode] = t[mode] or {}
|
|
||||||
t[mode][map] = scoreTable
|
|
||||||
end
|
|
||||||
|
|
||||||
local function getST(t, map, flags)
|
|
||||||
local mode = flags & ST_SEP
|
|
||||||
return t[mode] and t[mode][map] or nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local function setScoreTable(map, flags, scoreTable)
|
|
||||||
setST(lb, map, flags, scoreTable)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function getScoreTable(map, flags)
|
|
||||||
return getST(lb, map, flags)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- True if a is better than b
|
|
||||||
local function lbComp(a, b)
|
|
||||||
-- Calculates the difficulty, harder has higher priority
|
|
||||||
-- if s is positive then a is harder
|
|
||||||
-- if s is negative then b is harder
|
|
||||||
-- if s is 0 then compare time
|
|
||||||
local s = (a["flags"] & (F_SPBEXP | F_SPBBIG)) - (b["flags"] & (F_SPBEXP | F_SPBBIG))
|
|
||||||
return s > 0 or not(s < 0 or a["time"] >= b["time"])
|
|
||||||
end
|
|
||||||
|
|
||||||
local function sortScores()
|
|
||||||
for mode, t in pairs(lb) do
|
|
||||||
for map, scoreTable in pairs(t) do
|
|
||||||
table.sort(scoreTable, lbComp)
|
|
||||||
setScoreTable(map, mode, scoreTable)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Reinitialize lb based on new ST_SEP value
|
|
||||||
local function reinit_lb()
|
|
||||||
local nlb = {}
|
|
||||||
|
|
||||||
for mode, t in pairs(lb) do
|
|
||||||
for map, scoreTable in pairs(t) do
|
|
||||||
for i, score in ipairs(scoreTable) do
|
|
||||||
local st = getST(nlb, map, score["flags"]) or {}
|
|
||||||
table.insert(st, score)
|
|
||||||
setST(nlb, map, score["flags"], st)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
lb = nlb
|
|
||||||
sortScores()
|
|
||||||
end
|
|
||||||
|
|
||||||
local cv_spb_separate = CV_RegisterVar({
|
local cv_spb_separate = CV_RegisterVar({
|
||||||
name = "lb_spb_combined",
|
name = "lb_spb_combined",
|
||||||
defaultvalue = 1,
|
defaultvalue = 1,
|
||||||
flags = CV_NETVAR | CV_CALL | CV_NOINIT,
|
flags = CV_NETVAR | CV_CALL | CV_NOINIT,
|
||||||
PossibleValue = CV_YesNo,
|
PossibleValue = CV_YesNo,
|
||||||
func = function(v)
|
func = function(v)
|
||||||
local curSep = ST_SEP
|
|
||||||
|
|
||||||
if v.value then
|
if v.value then
|
||||||
ST_SEP = F_SPBATK
|
ST_SEP = F_SPBATK
|
||||||
else
|
else
|
||||||
ST_SEP = F_SPBATK | F_SPBBIG | F_SPBEXP
|
ST_SEP = F_SPBATK | F_SPBBIG | F_SPBEXP
|
||||||
end
|
end
|
||||||
|
|
||||||
if curSep != ST_SEP then
|
|
||||||
reinit_lb()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -256,80 +199,6 @@ end
|
|||||||
local MSK_SPEED = 0xF0
|
local MSK_SPEED = 0xF0
|
||||||
local MSK_WEIGHT = 0xF
|
local MSK_WEIGHT = 0xF
|
||||||
|
|
||||||
local function stat_t(speed, weight)
|
|
||||||
if speed and weight then
|
|
||||||
return (speed << 4) | weight
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
|
|
||||||
local function stat_str(stat)
|
|
||||||
if stat then
|
|
||||||
return string.format("%d%d", (stat & MSK_SPEED) >> 4, stat & MSK_WEIGHT)
|
|
||||||
end
|
|
||||||
|
|
||||||
return "0"
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Read the leaderboard
|
|
||||||
if isserver then
|
|
||||||
local f = io.open(FILENAME, "r")
|
|
||||||
if f then
|
|
||||||
for l in f:lines() do
|
|
||||||
-- Leaderboard is stored in the following tab separated format
|
|
||||||
-- mapnum, name, skin, color, time, splits, flags, stat
|
|
||||||
local t = {}
|
|
||||||
for word in (l+"\t"):gmatch("(.-)\t") do
|
|
||||||
table.insert(t, word)
|
|
||||||
end
|
|
||||||
|
|
||||||
local flags = 0
|
|
||||||
if t[7] != nil then
|
|
||||||
flags = tonumber(t[7])
|
|
||||||
end
|
|
||||||
|
|
||||||
scoreTable = getScoreTable(tonumber(t[1]), flags) or {}
|
|
||||||
|
|
||||||
local spl = {}
|
|
||||||
if t[6] != nil then
|
|
||||||
for str in t[6]:gmatch("([^ ]+)") do
|
|
||||||
table.insert(spl, tonumber(str))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local stats = nil
|
|
||||||
if t[8] != nil then
|
|
||||||
if #t[8] >= 2 then
|
|
||||||
local speed = tonumber(string.sub(t[8], 1, 1))
|
|
||||||
local weight = tonumber(string.sub(t[8], 2, 2))
|
|
||||||
stats = stat_t(speed, weight)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(
|
|
||||||
scoreTable,
|
|
||||||
score_t(
|
|
||||||
tonumber(t[1]),
|
|
||||||
t[2],
|
|
||||||
t[3],
|
|
||||||
t[4],
|
|
||||||
tonumber(t[5]),
|
|
||||||
spl,
|
|
||||||
flags,
|
|
||||||
stats
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
setScoreTable(tonumber(t[1]), flags, scoreTable)
|
|
||||||
end
|
|
||||||
|
|
||||||
sortScores()
|
|
||||||
f:close()
|
|
||||||
else
|
|
||||||
print("Failed to open file: ", FILENAME)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function allowJoin(v)
|
function allowJoin(v)
|
||||||
if not cv_interrupt.value then
|
if not cv_interrupt.value then
|
||||||
local y
|
local y
|
||||||
@ -423,7 +292,7 @@ local function initBrowser(player)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
InitBrowser(lb)
|
InitBrowser(ST_SEP)
|
||||||
drawState = DS_BROWSER
|
drawState = DS_BROWSER
|
||||||
|
|
||||||
player.afkTime = leveltime
|
player.afkTime = leveltime
|
||||||
@ -840,6 +709,8 @@ addHook("MapLoad", function()
|
|||||||
|
|
||||||
allowJoin(true)
|
allowJoin(true)
|
||||||
--printTable(lb)
|
--printTable(lb)
|
||||||
|
|
||||||
|
MapRecords = GetMapRecords(gamemap, ST_SEP)
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1150,12 +1021,14 @@ local function drawScoreboard(v, player)
|
|||||||
cachePatches(v)
|
cachePatches(v)
|
||||||
|
|
||||||
local gui = cv_gui.value
|
local gui = cv_gui.value
|
||||||
|
|
||||||
|
-- Force enable gui at start and end of the race
|
||||||
if leveltime < START_TIME or player.exiting or player.lives == 0 then
|
if leveltime < START_TIME or player.exiting or player.lives == 0 then
|
||||||
gui = GUI_ON
|
gui = GUI_ON
|
||||||
end
|
end
|
||||||
|
|
||||||
if gui then
|
if gui then
|
||||||
stateFunctions[drawState](v, player, scoreTable, gui)
|
stateFunctions[drawState](v, player, ScoreTable, gui)
|
||||||
end
|
end
|
||||||
|
|
||||||
local pos = 0
|
local pos = 0
|
||||||
@ -1195,7 +1068,7 @@ end
|
|||||||
|
|
||||||
-- Find location of player and scroll to it
|
-- Find location of player and scroll to it
|
||||||
function scroll_to(player)
|
function scroll_to(player)
|
||||||
local m = scoreTable or {}
|
local m = ScoreTable or {}
|
||||||
|
|
||||||
scrollToPos = 2
|
scrollToPos = 2
|
||||||
for pos, score in ipairs(m) do
|
for pos, score in ipairs(m) do
|
||||||
@ -1209,19 +1082,19 @@ function scroll_to(player)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Write skin stats to each score where there are none
|
-- Write skin stats to each score where there are none
|
||||||
local function writeStats()
|
--local function writeStats()
|
||||||
for _, t in pairs(lb) do
|
-- for _, t in pairs(lb) do
|
||||||
for _, scoreTable in pairs(t) do
|
-- for _, scoreTable in pairs(t) do
|
||||||
for _, score in ipairs(scoreTable) do
|
-- for _, score in ipairs(scoreTable) do
|
||||||
local skin = skins[score["skin"]]
|
-- local skin = skins[score["skin"]]
|
||||||
if skin and not score["stat"] then
|
-- if skin and not score["stat"] then
|
||||||
local stats = stat_t(skin.kartspeed, skin.kartweight)
|
-- local stats = stat_t(skin.kartspeed, skin.kartweight)
|
||||||
score["stat"] = stats
|
-- score["stat"] = stats
|
||||||
end
|
-- end
|
||||||
end
|
-- end
|
||||||
end
|
-- end
|
||||||
end
|
-- end
|
||||||
end
|
--end
|
||||||
|
|
||||||
local function checkFlags(p)
|
local function checkFlags(p)
|
||||||
local flags = 0
|
local flags = 0
|
||||||
@ -1261,7 +1134,7 @@ local function saveTime(player)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
scoreTable = $ or {}
|
ScoreTable = $ or {}
|
||||||
|
|
||||||
local pskin = skins[player.mo.skin]
|
local pskin = skins[player.mo.skin]
|
||||||
local newscore = score_t(
|
local newscore = score_t(
|
||||||
@ -1276,16 +1149,9 @@ local function saveTime(player)
|
|||||||
)
|
)
|
||||||
|
|
||||||
-- Check if you beat your previous best
|
-- Check if you beat your previous best
|
||||||
for i = 1, #scoreTable do
|
for i = 1, #ScoreTable do
|
||||||
if scoreTable[i]["name"] == player.name then
|
if ScoreTable[i].name == player.name then
|
||||||
if lbComp(newscore, scoreTable[i]) then
|
if not lbComp(newscore, ScoreTable[i]) then
|
||||||
table.remove(scoreTable, i)
|
|
||||||
S_StartSound(nil, 130)
|
|
||||||
FlashTics = leveltime + TICRATE * 3
|
|
||||||
FlashRate = 1
|
|
||||||
FlashVFlags = YellowFlash
|
|
||||||
break
|
|
||||||
else
|
|
||||||
-- You suck lol
|
-- You suck lol
|
||||||
S_StartSound(nil, 201)
|
S_StartSound(nil, 201)
|
||||||
FlashTics = leveltime + TICRATE * 3
|
FlashTics = leveltime + TICRATE * 3
|
||||||
@ -1297,61 +1163,33 @@ local function saveTime(player)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
print("Saving score")
|
|
||||||
table.insert(
|
|
||||||
scoreTable,
|
|
||||||
newscore
|
|
||||||
)
|
|
||||||
|
|
||||||
table.sort(scoreTable, lbComp)
|
-- Save the record
|
||||||
while #scoreTable > cv_saves.value do
|
SaveRecord(newscore, gamemap, ST_SEP)
|
||||||
table.remove(scoreTable)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
-- Set players text flash and play chime sfx
|
||||||
|
S_StartSound(nil, 130)
|
||||||
|
FlashTics = leveltime + TICRATE * 3
|
||||||
|
FlashRate = 1
|
||||||
|
FlashVFlags = YellowFlash
|
||||||
|
|
||||||
|
-- Reload the MapRecords
|
||||||
|
MapRecords = GetMapRecords(gamemap, ST_SEP)
|
||||||
|
|
||||||
|
-- Set the updated ScoreTable
|
||||||
|
ScoreTable = MapRecords[Flags]
|
||||||
|
|
||||||
|
-- Scroll the gui to the player entry
|
||||||
scroll_to(player)
|
scroll_to(player)
|
||||||
|
|
||||||
setScoreTable(gamemap, Flags, scoreTable)
|
|
||||||
|
|
||||||
if not StatTrack then
|
|
||||||
writeStats()
|
|
||||||
StatTrack = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if isserver then
|
|
||||||
local f = assert(io.open(FILENAME, "w"))
|
|
||||||
if f == nil then
|
|
||||||
print("Failed to open file for writing: " + FILENAME)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, tbl in pairs(lb) do
|
|
||||||
for _, scoreTable in pairs(tbl) do
|
|
||||||
for _, score in ipairs(scoreTable) do
|
|
||||||
f:write(
|
|
||||||
score["map"], "\t",
|
|
||||||
score["name"], "\t",
|
|
||||||
score["skin"], "\t",
|
|
||||||
score["color"], "\t",
|
|
||||||
score["time"], "\t",
|
|
||||||
table.concat(score["splits"], " "), "\t",
|
|
||||||
score["flags"], "\t",
|
|
||||||
stat_str(score["stat"]), "\n"
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
f:close()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- DEBUGGING
|
-- DEBUGGING
|
||||||
--local function saveLeaderboard(player, ...)
|
local function saveLeaderboard(player, ...)
|
||||||
-- timeFinished = tonumber(... or player.realtime)
|
timeFinished = tonumber(... or player.realtime)
|
||||||
-- splits = {1000, 2000, 3000}
|
splits = {1000, 2000, 3000}
|
||||||
-- saveTime(player)
|
saveTime(player)
|
||||||
--end
|
end
|
||||||
--COM_AddCommand("save", saveLeaderboard)
|
COM_AddCommand("save", saveLeaderboard)
|
||||||
|
|
||||||
local function regLap(player)
|
local function regLap(player)
|
||||||
if player.laps > prevLap and timeFinished == 0 then
|
if player.laps > prevLap and timeFinished == 0 then
|
||||||
@ -1461,7 +1299,7 @@ local function think()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
scoreTable = getScoreTable(gamemap, Flags)
|
ScoreTable = MapRecords[ST_SEP & Flags]
|
||||||
|
|
||||||
if not cv_teamchange then
|
if not cv_teamchange then
|
||||||
cv_teamchange = CV_FindVar("allowteamchange")
|
cv_teamchange = CV_FindVar("allowteamchange")
|
||||||
@ -1562,6 +1400,6 @@ local function netvars(net)
|
|||||||
drawState = net($)
|
drawState = net($)
|
||||||
StatTrack = net($)
|
StatTrack = net($)
|
||||||
EncoreInitial = net($)
|
EncoreInitial = net($)
|
||||||
lb = net($)
|
MapRecords = net($)
|
||||||
end
|
end
|
||||||
addHook("NetVars", netvars)
|
addHook("NetVars", netvars)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user