v1.1.1
This commit is contained in:
commit
f0703eaafd
218
leaderboard.lua
Normal file
218
leaderboard.lua
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
-- Leaderboards written by Not
|
||||||
|
|
||||||
|
local FILENAME = "leaderboard.txt"
|
||||||
|
local lb = {}
|
||||||
|
local timeFinished = 0
|
||||||
|
local disable = true
|
||||||
|
local prevLap = 0
|
||||||
|
local splits = {}
|
||||||
|
|
||||||
|
-- Read the leaderboard
|
||||||
|
local f = io.open(FILENAME, "r")
|
||||||
|
if f then
|
||||||
|
for l in f:lines() do
|
||||||
|
local t = {}
|
||||||
|
for word in (l+"\t"):gmatch("(.-)\t") do
|
||||||
|
table.insert(t, word)
|
||||||
|
end
|
||||||
|
--local level, name, skin, color, time, splts = l:match("(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)")
|
||||||
|
|
||||||
|
if lb[t[1]] == nil then
|
||||||
|
lb[t[1]] = {}
|
||||||
|
end
|
||||||
|
local spl = {}
|
||||||
|
if t[6] != nil then
|
||||||
|
for str in t[6]:gmatch("([^ ]+)") do
|
||||||
|
table.insert(spl, tonumber(str))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.insert(lb[t[1]], {t[2], t[3], t[4], tonumber(t[5]), spl})
|
||||||
|
end
|
||||||
|
f:close()
|
||||||
|
else
|
||||||
|
print("Failed to open file: ", FILENAME)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function initLeaderboard()
|
||||||
|
local ingame = 0
|
||||||
|
for p in players.iterate do
|
||||||
|
if p.valid and not p.spectator then
|
||||||
|
ingame = ingame + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
disable = ingame > 1
|
||||||
|
|
||||||
|
if disable then
|
||||||
|
--print("To many players in game, leaderboard has been disabled")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
addHook("PlayerSpawn", initLeaderboard)
|
||||||
|
|
||||||
|
local function retry(player, ...)
|
||||||
|
if disable or player.spectator then
|
||||||
|
print("How dare you")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
G_SetCustomExitVars(gamemap, 2)
|
||||||
|
G_ExitLevel()
|
||||||
|
end
|
||||||
|
COM_AddCommand("retry", retry)
|
||||||
|
|
||||||
|
|
||||||
|
--DEBUGGING
|
||||||
|
--local function printTable(tb)
|
||||||
|
-- for k, v in pairs(tb) do
|
||||||
|
-- for i = 1, #v do
|
||||||
|
-- print("TABLE: " + k, tb[k])
|
||||||
|
-- if v[i] != nil then
|
||||||
|
-- print(v[i][1], v[i][2], v[i][3], v[i][4], table.concat(v[i][5], ","))
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
--end
|
||||||
|
|
||||||
|
addHook("MapLoad", function()
|
||||||
|
timeFinished = 0
|
||||||
|
splits = {}
|
||||||
|
prevLap = 0
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
local function ticsToTime(tics)
|
||||||
|
return string.format(
|
||||||
|
"%d:%02d:%02d",
|
||||||
|
G_TicsToMinutes(tics),
|
||||||
|
G_TicsToSeconds(tics),
|
||||||
|
G_TicsToCentiseconds(tics)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
local bodium = {V_YELLOWMAP, V_GRAYMAP, V_BROWNMAP, 0, 0}
|
||||||
|
local splitColor = {[true]=V_SKYMAP, [false]=V_REDMAP}
|
||||||
|
local splitSymbol = {[true]="-", [false]="+"}
|
||||||
|
|
||||||
|
local showSplit = 0
|
||||||
|
local function drawScoreboard(v)
|
||||||
|
if disable then return end
|
||||||
|
|
||||||
|
local m = lb[tostring(gamemap)]
|
||||||
|
if m == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1, #m do
|
||||||
|
local score = m[i]
|
||||||
|
local skin = skins[score[2]]
|
||||||
|
if skin == nil then
|
||||||
|
skin = skins["sonic"]
|
||||||
|
end
|
||||||
|
|
||||||
|
local patch = v.cachePatch(skin.facerank)
|
||||||
|
-- | OFFSET | + | PADDING | * |INDEX|
|
||||||
|
local h = ((200 / 4) + 4) + (patch.height + 4) * (i - 1)
|
||||||
|
v.draw(4, h, patch, V_HUDTRANS | bodium[i], v.getColormap("sonic", score[3]))
|
||||||
|
v.drawString(8 + patch.width, h, score[1], V_HUDTRANSHALF | V_ALLOWLOWERCASE)
|
||||||
|
|
||||||
|
-- Draw splits
|
||||||
|
if showSplit > 0 and score[5][prevLap] != nil then
|
||||||
|
local split = splits[prevLap] - score[5][prevLap]
|
||||||
|
v.drawString(8 + patch.width, h + 8, splitSymbol[split < 0] + ticsToTime(abs(split)), V_HUDTRANSHALF | splitColor[split < 0])
|
||||||
|
else
|
||||||
|
v.drawString(8 + patch.width, h + 8, ticsToTime(score[4]), V_HUDTRANSHALF | bodium[i])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
hud.add(drawScoreboard, "game")
|
||||||
|
|
||||||
|
local function lbComp(a, b)
|
||||||
|
return a[4] < b[4]
|
||||||
|
end
|
||||||
|
|
||||||
|
local function saveTime(player)
|
||||||
|
-- Check if you beat your previous best
|
||||||
|
local m = lb[tostring(gamemap)]
|
||||||
|
if m == nil then
|
||||||
|
m = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1, #m do
|
||||||
|
if m[i][1] == player.name then
|
||||||
|
if m[i][4] > timeFinished then
|
||||||
|
table.remove(m, i)
|
||||||
|
S_StartSound(nil, 130)
|
||||||
|
break
|
||||||
|
else
|
||||||
|
-- You suck lol
|
||||||
|
S_StartSound(nil, 201)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
print("Saving score")
|
||||||
|
table.insert(m, {player.name, player.mo.skin, player.mo.color, timeFinished, splits})
|
||||||
|
|
||||||
|
table.sort(m, lbComp)
|
||||||
|
while #m > 5 do
|
||||||
|
table.remove(m)
|
||||||
|
end
|
||||||
|
|
||||||
|
lb[tostring(gamemap)] = m
|
||||||
|
|
||||||
|
local f = assert(io.open(FILENAME, "w"))
|
||||||
|
if f == nil then
|
||||||
|
print("Failed to open file for writing: " + FILENAME)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
for k, v in pairs(lb) do
|
||||||
|
for i = 1, #v do
|
||||||
|
local s = v[i]
|
||||||
|
f:write(k, "\t", s[1], "\t", s[2], "\t", s[3], "\t", s[4], "\t", table.concat(s[5], " "), "\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DEBUGGING
|
||||||
|
--local function saveLeaderboard(player, ...)
|
||||||
|
-- timeFinished = player.realtime
|
||||||
|
-- splits = {1000, 2000, 3000}
|
||||||
|
-- saveTime(player)
|
||||||
|
--end
|
||||||
|
--COM_AddCommand("save", saveLeaderboard)
|
||||||
|
|
||||||
|
local function regLap(player)
|
||||||
|
if player.laps > prevLap and timeFinished == 0 then
|
||||||
|
prevLap = player.laps
|
||||||
|
table.insert(splits, player.realtime)
|
||||||
|
showSplit = 5 * TICRATE
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function captureFinish()
|
||||||
|
if disable then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if showSplit > 0 then
|
||||||
|
showSplit = showSplit - 1
|
||||||
|
end
|
||||||
|
|
||||||
|
for p in players.iterate do
|
||||||
|
if p.laps >= mapheaderinfo[gamemap].numlaps and timeFinished == 0 then
|
||||||
|
timeFinished = p.realtime
|
||||||
|
saveTime(p)
|
||||||
|
end
|
||||||
|
regLap(p)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
addHook("ThinkFrame", captureFinish)
|
||||||
|
|
||||||
|
local function netvars(net)
|
||||||
|
lb = net($)
|
||||||
|
end
|
||||||
|
addHook("NetVars", netvars)
|
Loading…
Reference in New Issue
Block a user