local serverSkins = {} // Just in case! local function syncSkins(net) serverSkins = net($) end addHook("NetVars", syncSkins) // Self-explanatory. // Save the list of players alongside the name of the skin they're using. // Example: $HOME;sonic local function _saveSkinsToFile() local f = assert(io.open("ServerSkinsData.txt", "w+")) // {playerName, skin name} local dataString = "" for player, skin in pairs(serverSkins) do if player:find(";") then continue end -- sanity check dataString = $..player..";"..skin.."\n" end f:write(dataString) f:close() end // Why, yes, this is from stattracker! Thank you, Onyo. local function outputSkins() if consoleplayer ~= server then return end if not pcall(_saveSkinsToFile) then print("Failed to save skins to file!") else CONS_Printf(server, "Saved skins.") end end // Do this once at the start of each race. // Would do it during intermission, but we have RTVs and the sort. local function saveSkinsAtStartOfRace() if (leveltime == 8) then if #serverSkins ~= 0 then serverSkins = {} end for p in players.iterate do local playerMoExists = (p and p.mo ~= nil and p.mo.valid) local playerMoSkin = "sonic" if (playerMoExists) then playerMoSkin = p.mo.skin else if (p.serverfakeskin and p.serverfakeskin ~= nil) then playerMoSkin = p.serverfakeskin end end serverSkins[p.name] = skins[playerMoSkin].name end outputSkins() end for p in players.iterate do // Skin variable only exists in p.mo. When players spectate, p.mo is nil. // Just save it to a backup variable just in case. if not (p and p.mo ~= nil and p.mo.valid) then return end p.serverfakeskin = p.mo.skin end end addHook("ThinkFrame", saveSkinsAtStartOfRace)