Files
zkldi_Tachi/database-seeds/scripts/rerunners/stepmania/waterfall-hijack.patch
T
2022-06-12 17:29:46 +01:00

1219 lines
63 KiB
Diff

diff --git a/Scripts/WF-Profiles.lua b/Scripts/WF-Profiles.lua
index 2c87831..6b62c0c 100644
--- a/Scripts/WF-Profiles.lua
+++ b/Scripts/WF-Profiles.lua
@@ -16,19 +16,26 @@
-- HERE IT IS BOYS. IT'S THE HASH CACHE #HASHCASH
WF.HashCache = {}
+-- HERE IT IS BOYS. IT'S THE ZKLDI CACHE #ZCACHE
+-- we hijack this process to create useful chart info ourselves
+-- i'm too lazy to write my own proper sm parser
+-- and sm sucks
+-- sorry not sorry
+WF.ZkldiDump = {};
+
WF.InitPlayerProfiles = function()
- -- these will always be indexed by player number
+ -- these will always be indexed by player number
WF.PlayerProfileStats = {}
-- there will be some checks for the validity of a profile when loaded, and if it's found to be invalid, set a
-- flag to indicate not to try to save anything
- WF.ProfileInvalid = {false,false}
+ WF.ProfileInvalid = { false, false }
-- this is just my own variable to keep track of how many songs has been played per player
- WF.CurrentSessionSongsPlayed = {0,0}
+ WF.CurrentSessionSongsPlayed = { 0, 0 }
-- subtitle to appear under name on profile card
- WF.ProfileCardSubtitle = {"",""}
+ WF.ProfileCardSubtitle = { "", "" }
end
WF.InitPlayerProfiles()
@@ -151,17 +158,17 @@ WF.NewPlayerProfileSongStats = function()
BestPercentDP = 0,
BestPercentDP_ITG = 0,
Cleared_ITG = nil,
- BestFAPlusCounts = {0,0,0},
+ BestFAPlusCounts = { 0, 0, 0 },
TotalSteps = 0,
TotalHolds = 0,
TotalRolls = 0,
TotalMines = 0,
BestPlay = {
DateObtained = "0000-00-00 00:00:00",
- Judgments = {0,0,0,0,0,0,0,0,0},
- FAPlus = {0,0},
- LifeBarVals = {1000,1000,1000},
- ScoreAtLifeEmpty = {0,0,0},
+ Judgments = { 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ FAPlus = { 0, 0 },
+ LifeBarVals = { 1000, 1000, 1000 },
+ ScoreAtLifeEmpty = { 0, 0, 0 },
SignificantMods = {}
}
}
@@ -191,7 +198,7 @@ WF.MergePlayerProfileSongStats = function(stats1, stats2)
-- exit if hash and rate aren't the same (no reason to ever merge in this case, so catch it here and log it)
if (not ((not iscourse) and stats1.ChartHash == stats2.ChartHash and stats1.RateMod == stats2.RateMod))
- and (not ((iscourse) and stats1.CourseID == stats2.CourseID and stats1.RateMod == stats2.RateMod)) then
+ and (not ((iscourse) and stats1.CourseID == stats2.CourseID and stats1.RateMod == stats2.RateMod)) then
Trace(string.format("Stats merge error:\nhash/id 1: %s\nrate 1: %s\nhash/id 2: %s\nrate 2:%s",
iscourse and stats1.CourseID or stats1.ChartHash, stats1.RateMod,
iscourse and stats2.CourseID or stats2.ChartHash, stats2.RateMod))
@@ -250,8 +257,8 @@ WF.ConsolidateProfileSongAndCourseStats = function(pn)
-- first loop through and reassign bad hashes; this needs to be done in a separate loop
for score in ivalues(stats) do
if (WF.HashCache) and (score.ChartHash) and (score.ChartHash ~= "") and (score.ChartID)
- and (score.ChartID ~= "") and (WF.HashCache[score.ChartID])
- and (score.ChartHash ~= WF.HashCache[score.ChartID]) then
+ and (score.ChartID ~= "") and (WF.HashCache[score.ChartID])
+ and (score.ChartHash ~= WF.HashCache[score.ChartID]) then
score.ChartHash = WF.HashCache[score.ChartID]
end
end
@@ -305,7 +312,7 @@ end
WF.AddPlayerProfileSongStatsFromSteps = function(song, steps, rate, hash, pn)
-- create a new stats object with information from the song and steps passed (and optional rate mod),
-- and add it to the player profile stats table.
- local player = "PlayerNumber_P"..pn
+ local player = "PlayerNumber_P" .. pn
if not song then
song = (not GAMESTATE:IsCourseMode()) and GAMESTATE:GetCurrentSong() or GAMESTATE:GetCurrentCourse()
@@ -323,7 +330,7 @@ WF.AddPlayerProfileSongStatsFromSteps = function(song, steps, rate, hash, pn)
WF.SongStatsUpdateChartAttributes(stats, song, steps, hash, pn)
stats.RateMod = rate
stats.PlayCount = 0
-
+
WF.AddSongStatsToProfile(stats, pn)
return stats
end
@@ -339,7 +346,7 @@ WF.SavePlayerProfileStats = function(pn)
local stats = WF.PlayerProfileStats[pn]
if (not stats) or stats == {} then return end
- local dir = PROFILEMAN:GetProfileDir("ProfileSlot_Player"..pn)
+ local dir = PROFILEMAN:GetProfileDir("ProfileSlot_Player" .. pn)
if (not dir) or dir == "" then return end
-- table for all sections of the file
@@ -347,7 +354,8 @@ WF.SavePlayerProfileStats = function(pn)
-- first, the general stats
local statsstr = string.format("#STATS\n%s\n%d\n%d\n%d\n%d,%d,%d,%d,%d,%d\n%d,%d\n%d,%d\n%d,%d\n%s\n%s",
- GetThemeVersion(), stats.SkillLv, stats.SongsPlayed, stats.CoursesPlayed, stats.TotalTapJudgments[1], stats.TotalTapJudgments[2],
+ GetThemeVersion(), stats.SkillLv, stats.SongsPlayed, stats.CoursesPlayed, stats.TotalTapJudgments[1],
+ stats.TotalTapJudgments[2],
stats.TotalTapJudgments[3], stats.TotalTapJudgments[4], stats.TotalTapJudgments[5], stats.TotalTapJudgments[6],
stats.TotalHolds[1], stats.TotalHolds[2], stats.TotalHolds[3], stats.TotalHolds[4],
stats.TotalMines[1], stats.TotalMines[2], stats.LastSongPlayed, stats.LastPlayedDate)
@@ -357,7 +365,7 @@ WF.SavePlayerProfileStats = function(pn)
for chart in ivalues(stats.SongStats) do
-- first, the general stats for the chart
local hash = chart.ChartHash and chart.ChartHash or "-"
- local itgdp = tostring(chart.BestPercentDP_ITG)..(chart.Cleared_ITG or "")
+ local itgdp = tostring(chart.BestPercentDP_ITG) .. (chart.Cleared_ITG or "")
table.insert(ft, string.format("#SONG\n%s\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%d\n%s\n%d,%d,%d\n%d\n%d,%d,%d",
chart.SongFullTitle, chart.SongArtist, chart.BPM, hash, chart.ChartID, chart.RateMod,
chart.DifficultyRating, chart.PlayCount, chart.BestClearType, chart.BestPercentDP, itgdp,
@@ -380,7 +388,7 @@ WF.SavePlayerProfileStats = function(pn)
-- repeat above for courses
for course in ivalues(stats.CourseStats) do
-- first, the general stats for the course
- local itgdp = tostring(course.BestPercentDP_ITG)..(course.Cleared_ITG or "")
+ local itgdp = tostring(course.BestPercentDP_ITG) .. (course.Cleared_ITG or "")
table.insert(ft, string.format("#COURSE\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%d\n%s\n%d,%d,%d\n%d\n%d,%d,%d",
course.CourseTitle, course.BPM, course.CourseID, course.RateMod,
course.DifficultyRating, course.PlayCount, course.BestClearType, course.BestPercentDP, itgdp,
@@ -409,16 +417,16 @@ WF.SavePlayerProfileStats = function(pn)
-- write file
local fstr = table.concat(ft, "\n")
- if File.Write(dir.."/PlayerStats.wfs",fstr) then
- Trace("Player "..pn.." profile stats saved.")
+ if File.Write(dir .. "/PlayerStats.wfs", fstr) then
+ Trace("Player " .. pn .. " profile stats saved.")
else
- SM("Player "..pn.." profile stats failed to save!")
+ SM("Player " .. pn .. " profile stats failed to save!")
end
end
WF.LoadPlayerProfileStats = function(pn)
-- Load all the stats from the main stats file
- local dir = PROFILEMAN:GetProfileDir("ProfileSlot_Player"..pn)
+ local dir = PROFILEMAN:GetProfileDir("ProfileSlot_Player" .. pn)
WF.ProfileCardSubtitle[pn] = ""
if (not dir) or dir == "" then
-- nil the stats here and exit; this essentially means a guest profile is being used
@@ -429,24 +437,24 @@ WF.LoadPlayerProfileStats = function(pn)
local stats = WF.ProfileStatsTemplate()
-- get subtitle for profile card
- if FILEMAN:DoesFileExist(dir.."/subtitle.txt") then
- WF.ProfileCardSubtitle[pn] = File.Read(dir.."/subtitle.txt")
+ if FILEMAN:DoesFileExist(dir .. "/subtitle.txt") then
+ WF.ProfileCardSubtitle[pn] = File.Read(dir .. "/subtitle.txt")
-- some light processing, since who knows what people will write in there
WF.ProfileCardSubtitle[pn] = (WF.ProfileCardSubtitle[pn]:gsub("[\r\f\n]", " ")):sub(1, 20)
else
- File.Write(dir.."/subtitle.txt", "")
+ File.Write(dir .. "/subtitle.txt", "")
end
- if not FILEMAN:DoesFileExist(dir.."/PlayerStats.wfs") then
+ if not FILEMAN:DoesFileExist(dir .. "/PlayerStats.wfs") then
-- file has not been created; just return
WF.PlayerProfileStats[pn] = stats
return
end
- local sfile = File.Read(dir.."/PlayerStats.wfs")
+ local sfile = File.Read(dir .. "/PlayerStats.wfs")
if not sfile then
-- error loading file
- SM("Error loading stats for player "..pn.."!")
+ SM("Error loading stats for player " .. pn .. "!")
WF.PlayerProfileStats[pn] = nil
return
end
@@ -501,8 +509,8 @@ WF.LoadPlayerProfileStats = function(pn)
stats.ForceImportCourses = true -- force course import since they weren't available before
-- back up old player stats file
- if not FILEMAN:DoesFileExist(dir.."/PlayerStats_062") then
- File.Write(dir.."/PlayerStats_062", sfile)
+ if not FILEMAN:DoesFileExist(dir .. "/PlayerStats_062") then
+ File.Write(dir .. "/PlayerStats_062", sfile)
end
-- back up ecfa stats file if exists
BackUpECFA2021Stats(dir)
@@ -520,11 +528,11 @@ WF.LoadPlayerProfileStats = function(pn)
elseif l == 5 then
-- judgment counts
local judges = line:split_tonumber()
- stats.TotalTapJudgments = {judges[1],judges[2],judges[3],judges[4],judges[5],judges[6]}
+ stats.TotalTapJudgments = { judges[1], judges[2], judges[3], judges[4], judges[5], judges[6] }
elseif l == 6 then
-- holds
local holds = line:split_tonumber()
- stats.TotalHolds = {holds[1],holds[2],0,0}
+ stats.TotalHolds = { holds[1], holds[2], 0, 0 }
elseif l == 7 then
-- rolls
local rolls = line:split_tonumber()
@@ -533,7 +541,7 @@ WF.LoadPlayerProfileStats = function(pn)
elseif l == 8 then
-- mines
local mines = line:split_tonumber()
- stats.TotalMines = {mines[1],mines[2]}
+ stats.TotalMines = { mines[1], mines[2] }
elseif l == 9 then
-- last song played
stats.LastSongPlayed = line
@@ -597,7 +605,7 @@ WF.LoadPlayerProfileStats = function(pn)
elseif l == 12 then
-- high fa+ counts
local counts = line:split_tonumber()
- song.BestFAPlusCounts = {counts[1],counts[2],counts[3]}
+ song.BestFAPlusCounts = { counts[1], counts[2], counts[3] }
elseif l == 13 then
-- total steps
song.TotalSteps = tonumber(line)
@@ -614,7 +622,7 @@ WF.LoadPlayerProfileStats = function(pn)
elseif l == 16 then
-- tap judgments
local counts = line:split_tonumber()
- song.BestPlay.Judgments = {counts[1],counts[2],counts[3],counts[4],counts[5],counts[6],0,0,0}
+ song.BestPlay.Judgments = { counts[1], counts[2], counts[3], counts[4], counts[5], counts[6], 0, 0, 0 }
elseif l == 17 then
-- hold judgments
local held = line:split_tonumber()
@@ -626,15 +634,15 @@ WF.LoadPlayerProfileStats = function(pn)
elseif l == 19 then
-- fa+
local counts = line:split_tonumber()
- song.BestPlay.FAPlus = {counts[1],counts[2]}
+ song.BestPlay.FAPlus = { counts[1], counts[2] }
elseif l == 20 then
-- lifebar vals
local vals = line:split_tonumber()
- song.BestPlay.LifeBarVals = {vals[1],vals[2],vals[3]}
+ song.BestPlay.LifeBarVals = { vals[1], vals[2], vals[3] }
elseif l == 21 then
-- score at life empty
local vals = line:split_tonumber()
- song.BestPlay.ScoreAtLifeEmpty = {vals[1],vals[2],vals[3]}
+ song.BestPlay.ScoreAtLifeEmpty = { vals[1], vals[2], vals[3] }
elseif l == 22 then
-- significant mods
local mods = split(",", line)
@@ -662,7 +670,7 @@ WF.LoadPlayerProfileStats = function(pn)
WF.PreloadClearsAndGrades(pn)
end
- Trace("Player "..pn.." profile stats loaded.")
+ Trace("Player " .. pn .. " profile stats loaded.")
end
WF.CalculateClearTypeAndGradeCounts = function(pn)
@@ -670,12 +678,12 @@ WF.CalculateClearTypeAndGradeCounts = function(pn)
local stats = WF.PlayerProfileStats[pn]
if not stats then return end
- stats.ClearTypeCounts = {0,0,0,0,0,0,0,0, 0} -- last index here is basically a dummy for unplayed
- stats.GradeCounts = {0,0,0,0,0,0,0}
- stats.GradeCounts_ITG = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
- stats.CourseClearTypeCounts = {0,0,0,0,0,0,0,0, 0}
- stats.CourseGradeCounts = {0,0,0,0,0,0,0}
- stats.CourseGradeCounts_ITG = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
+ stats.ClearTypeCounts = { 0, 0, 0, 0, 0, 0, 0, 0, 0 } -- last index here is basically a dummy for unplayed
+ stats.GradeCounts = { 0, 0, 0, 0, 0, 0, 0 }
+ stats.GradeCounts_ITG = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+ stats.CourseClearTypeCounts = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+ stats.CourseGradeCounts = { 0, 0, 0, 0, 0, 0, 0 }
+ stats.CourseGradeCounts_ITG = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
for song in ivalues(stats.SongStats) do
stats.ClearTypeCounts[song.BestClearType] = stats.ClearTypeCounts[song.BestClearType] + 1
@@ -703,15 +711,15 @@ WF.ProfileStatsTemplate = function()
SkillLv = 0,
SongsPlayed = 0,
CoursesPlayed = 0,
- TotalTapJudgments = {0,0,0,0,0,0},
- TotalHolds = {0,0,0,0},
- TotalMines = {0,0},
+ TotalTapJudgments = { 0, 0, 0, 0, 0, 0 },
+ TotalHolds = { 0, 0, 0, 0 },
+ TotalMines = { 0, 0 },
LastSongPlayed = "3D Movie Maker/Bistro Evil Theme",
LastPlayedDate = WF.DateString(),
- ClearTypeCounts = {0,0,0,0,0,0,0,0},
- GradeCounts = {0,0,0,0,0,0,0},
- SessionAchievements = {0,0,0,0,0,0,0},
+ ClearTypeCounts = { 0, 0, 0, 0, 0, 0, 0, 0 },
+ GradeCounts = { 0, 0, 0, 0, 0, 0, 0 },
+ SessionAchievements = { 0, 0, 0, 0, 0, 0, 0 },
GroupClearsAndGrades = {},
@@ -738,10 +746,10 @@ WF.WriteDetailedHighScoreStats = function(pn, hsitem, filenameext, filename, cou
local song, steps, detailed
if not courseind then
song = GAMESTATE:GetCurrentSong()
- steps = GAMESTATE:GetCurrentSteps("PlayerNumber_P"..pn)
- detailed = SL["P"..pn].Stages.Stats[SL.Global.Stages.PlayedThisGame + 1].detailed_judgments
+ steps = GAMESTATE:GetCurrentSteps("PlayerNumber_P" .. pn)
+ detailed = SL["P" .. pn].Stages.Stats[SL.Global.Stages.PlayedThisGame + 1].detailed_judgments
else
- local te = GAMESTATE:GetCurrentTrail("PlayerNumber_P"..pn):GetTrailEntry(courseind-1)
+ local te = GAMESTATE:GetCurrentTrail("PlayerNumber_P" .. pn):GetTrailEntry(courseind - 1)
song = te:GetSong()
steps = te:GetSteps()
detailed = WF.DetailedJudgmentsPerSongInCourse[pn][courseind]
@@ -751,7 +759,7 @@ WF.WriteDetailedHighScoreStats = function(pn, hsitem, filenameext, filename, cou
local hashorid = hsitem and (hsitem.ChartHash and hsitem.ChartHash or hsitem.ChartID)
- local abbrev = {Miss = "M", Held = "H", LetGo = "D", HitMine = "N"}
+ local abbrev = { Miss = "M", Held = "H", LetGo = "D", HitMine = "N" }
-- file string will be built from a table to avoid using .. which is bad on performance
local ft = {}
@@ -759,7 +767,7 @@ WF.WriteDetailedHighScoreStats = function(pn, hsitem, filenameext, filename, cou
if not hsitem then
-- create a dummy (haha dummy!!!! HHHASHAHAHAHHSH) hsitem from steps if none is passed in
-- steps can be passed in as an argument, which is useful for courses
- local player = "PlayerNumber_P"..pn
+ local player = "PlayerNumber_P" .. pn
hsitem = WF.NewPlayerProfileSongStats()
local id = WF.GetStepsID(song, steps)
hashorid = WF.HashCache[id]
@@ -774,14 +782,15 @@ WF.WriteDetailedHighScoreStats = function(pn, hsitem, filenameext, filename, cou
end
local fname = filename or LookupIdentifier(hashorid, hsitem.RateMod):gsub("/", "]]][[[")
- if filenameext then fname = fname..filenameext end
- local fullpath = PROFILEMAN:GetProfileDir("ProfileSlot_Player"..pn).."/detailed/"..fname
+ if filenameext then fname = fname .. filenameext end
+ local fullpath = PROFILEMAN:GetProfileDir("ProfileSlot_Player" .. pn) .. "/detailed/" .. fname
-- general info
local smods = (#hsitem.BestPlay.SignificantMods > 0) and table.concat(hsitem.BestPlay.SignificantMods, ",") or "-"
local songstr = string.format("%s\n%s\n%s\n%s\n%s\n%d\n%s\n%s\n%d\n%d\n%d\n%d\n%d\n%d\n%s",
GetThemeVersion(), hsitem.SongFullTitle, hsitem.SongArtist, hsitem.BPM, hsitem.ChartID, hsitem.DifficultyRating,
- hsitem.BestPlay.DateObtained, hsitem.RateMod, hsitem.TotalSteps, hsitem.TotalHolds, hsitem.BestPlay.Judgments[7],
+ hsitem.BestPlay.DateObtained, hsitem.RateMod, hsitem.TotalSteps, hsitem.TotalHolds, hsitem.BestPlay.Judgments[7]
+ ,
hsitem.TotalRolls, hsitem.BestPlay.Judgments[8], hsitem.TotalMines, smods)
table.insert(ft, songstr)
@@ -792,7 +801,7 @@ WF.WriteDetailedHighScoreStats = function(pn, hsitem, filenameext, filename, cou
local off = (#judge == 3 or judge[2] == "Miss") and abbrev[judge[2]] or string.format("%f", judge[4])
table.insert(ft, string.format("%f;%s;%s", judge[1], off, p))
end
-
+
table.insert(ft, "")
local fstr = table.concat(ft, "\n")
@@ -813,7 +822,7 @@ WF.WriteDetailedHighScoreStatsFromCourseList = function(pn, filenameext, list)
-- don't ever use the word leveraged in that way, it's really dumb ok
local count = 0
for ind in ivalues(list) do
- if WF.WriteDetailedHighScoreStats(pn, nil, filenameext, nil, ind) then
+ if WF.WriteDetailedHighScoreStats(pn, nil, filenameext, nil, ind) then
count = count + 1
end
end
@@ -829,18 +838,18 @@ WF.WriteAllDetailedHighScoresForCourse = function(pn, wfuslist, itguslist)
-- save each individual file to saved directory
for i = 1, #WF.DetailedJudgmentsPerSongInCourse[pn] do
- local te = GAMESTATE:GetCurrentTrail("PlayerNumber_P"..pn):GetTrailEntry(i-1)
+ local te = GAMESTATE:GetCurrentTrail("PlayerNumber_P" .. pn):GetTrailEntry(i - 1)
local song = te:GetSong()
local steps = te:GetSteps()
local songtitle = (song:GetDisplayMainTitle():gsub("[^A-Z^a-z^0-9]", ""))
- if (not songtitle) or (songtitle == "") then
- songtitle = (song:GetTranslitMainTitle():gsub("[^A-Z^a-z^0-9]", ""))
- end
- if (not songtitle) or (songtitle == "") then songtitle = "UnknownSong" end
- local diff = THEME:GetString("Difficulty",
- ToEnumShortString(steps:GetDifficulty()))
- local datestr = (WF.DateTimeString():gsub(":", ""):gsub(" ", "_"))
- local fname = "/saved/"..songtitle.."_"..diff.."_"..datestr
+ if (not songtitle) or (songtitle == "") then
+ songtitle = (song:GetTranslitMainTitle():gsub("[^A-Z^a-z^0-9]", ""))
+ end
+ if (not songtitle) or (songtitle == "") then songtitle = "UnknownSong" end
+ local diff = THEME:GetString("Difficulty",
+ ToEnumShortString(steps:GetDifficulty()))
+ local datestr = (WF.DateTimeString():gsub(":", ""):gsub(" ", "_"))
+ local fname = "/saved/" .. songtitle .. "_" .. diff .. "_" .. datestr
if WF.WriteDetailedHighScoreStats(pn, nil, nil, fname, i) then
count = count + 1
@@ -932,7 +941,7 @@ WF.MergeMachineProfileSongStats = function(stats1, stats2)
local newstats = WF.NewMachineProfileSongStats()
if (not ((not iscourse) and stats1.ChartHash == stats2.ChartHash and stats1.RateMod == stats2.RateMod))
- and (not ((iscourse) and stats1.CourseID == stats2.CourseID and stats1.RateMod == stats2.RateMod)) then
+ and (not ((iscourse) and stats1.CourseID == stats2.CourseID and stats1.RateMod == stats2.RateMod)) then
Trace(string.format("Stats merge error:\nhash/id 1: %s\nrate 1: %s\nhash/id 2: %s\nrate 2:%s",
(not iscourse) and stats1.ChartHash or stats1.CourseID, stats1.RateMod,
(not iscourse) and stats2.ChartHash or stats2.CourseID, stats2.RateMod))
@@ -996,7 +1005,7 @@ WF.SongStatsUpdateChartAttributes = function(stats, song, steps, hash, pn)
-- a player song stats object, meaning step counts etc will need to be updated too.
local iscourse = (stats.CourseTitle ~= nil) -- if course, "song" is course and "steps" is trail
local player
- if pn then player = "PlayerNumber_P"..pn end
+ if pn then player = "PlayerNumber_P" .. pn end
local id = WF.GetItemID(song, steps)
-- generate hash if one isn't passed in (better to not parse again if we don't need to)
@@ -1053,7 +1062,7 @@ WF.AddMachineProfileSongStatsFromSteps = function(song, steps, rate, hash, playe
WF.SongStatsUpdateChartAttributes(stats, song, steps, hash)
stats.RateMod = rate
stats.PlayCount = 0
-
+
WF.AddSongStatsToProfile(stats)
return stats
end
@@ -1127,11 +1136,11 @@ WF.SaveMachineProfileStats = function()
song.BPM, hash, song.ChartID, song.RateMod, song.DifficultyRating, song.PlayCount))
for score in ivalues(song.HighScoreList) do
table.insert(ft, string.format("$SCORE\n%s\n%s\n%s\n%s\n%d", score.PlayerFullName, score.PlayerHSName,
- score.PlayerGuid, score.DateObtained, score.PercentDP))
+ score.PlayerGuid, score.DateObtained, score.PercentDP))
end
for score in ivalues(song.HighScoreList_ITG) do
table.insert(ft, string.format("$ITG\n%s\n%s\n%s\n%s\n%d", score.PlayerFullName, score.PlayerHSName,
- score.PlayerGuid, score.DateObtained, score.PercentDP))
+ score.PlayerGuid, score.DateObtained, score.PercentDP))
end
end
@@ -1141,11 +1150,11 @@ WF.SaveMachineProfileStats = function()
course.BPM, course.CourseID, course.RateMod, course.DifficultyRating, course.PlayCount))
for score in ivalues(course.HighScoreList) do
table.insert(ft, string.format("$SCORE\n%s\n%s\n%s\n%s\n%d", score.PlayerFullName, score.PlayerHSName,
- score.PlayerGuid, score.DateObtained, score.PercentDP))
+ score.PlayerGuid, score.DateObtained, score.PercentDP))
end
for score in ivalues(course.HighScoreList_ITG) do
table.insert(ft, string.format("$ITG\n%s\n%s\n%s\n%s\n%d", score.PlayerFullName, score.PlayerHSName,
- score.PlayerGuid, score.DateObtained, score.PercentDP))
+ score.PlayerGuid, score.DateObtained, score.PercentDP))
end
end
@@ -1153,7 +1162,7 @@ WF.SaveMachineProfileStats = function()
-- write to file
local fstr = table.concat(ft, "\n")
- if File.Write(dir.."/MachineStats.wfm",fstr) then
+ if File.Write(dir .. "/MachineStats.wfm", fstr) then
Trace("Machine profile stats saved.")
else
SM("Machine profile stats failed to save!")
@@ -1176,12 +1185,12 @@ WF.LoadMachineProfileStats = function()
WF.MachineProfileStats = WF.MachineProfileStatsTemplate()
- if not FILEMAN:DoesFileExist(dir.."/MachineStats.wfm") then
+ if not FILEMAN:DoesFileExist(dir .. "/MachineStats.wfm") then
-- file has not been created; just return
return
end
- local sfile = File.Read(dir.."/MachineStats.wfm")
+ local sfile = File.Read(dir .. "/MachineStats.wfm")
if not sfile then
-- error loading file
SM("Error loading stats for machine profile!")
@@ -1251,7 +1260,7 @@ WF.LoadMachineProfileStats = function()
score.PercentDP = tonumber(line)
-- insert into corresponding table
local ext = (token == "ITG") and "_ITG" or ""
- curstats["HighScoreList"..ext][#curstats["HighScoreList"..ext]+1] = score
+ curstats["HighScoreList" .. ext][#curstats["HighScoreList" .. ext] + 1] = score
end
end
end
@@ -1269,7 +1278,7 @@ end
WF.FindProfileSongStats = function(hashorid, rate, pn)
-- pass in either a hash or a chart id. simple logic will determine which to use.
local identifier = hashorid:match("/") and "ChartID" or "ChartHash"
-
+
-- pass no pn for machine profile
local stats = pn ~= nil and WF.PlayerProfileStats[pn] or WF.MachineProfileStats
if not stats then return end
@@ -1421,13 +1430,13 @@ WF.UpdateProfilesOnEvaluation = function(hashes)
local pn = tonumber(player:sub(-1))
local steps = (not iscourse) and GAMESTATE:GetCurrentSteps(player) or GAMESTATE:GetCurrentTrail(player)
allitems[pn] = {}
- table.insert(allitems[pn], {song, steps})
+ table.insert(allitems[pn], { song, steps })
if iscourse then
for i = 1, WF.CurrentSongInCourse do
- local te = steps:GetTrailEntry(i-1)
+ local te = steps:GetTrailEntry(i - 1)
local songincourse = te:GetSong()
local stepsincourse = te:GetSteps()
- table.insert(allitems[pn], {songincourse, stepsincourse})
+ table.insert(allitems[pn], { songincourse, stepsincourse })
end
end
end
@@ -1464,16 +1473,16 @@ WF.UpdateProfilesOnEvaluation = function(hashes)
local itgdata = (not iscourse) and WF.ITGJudgmentData[pn]
or WF.ITGJudgmentData[pn][WF.CurrentSongInCourse]
local ts = itgdata[#itgdata] and (itgdata[#itgdata][3] + 0.02) or 0.1
- table.insert(itgdata, {nil, 0, ts})
+ table.insert(itgdata, { nil, 0, ts })
-- now just insert into wf lifebar tables
- for i = 1, #WF.LifeBarNames do
+ for i = 1, #WF.LifeBarNames do
if WF.LifeBarChanges[pn][i] then
-- reuse ts here because itg tracks life at every judgment rather than just changes
-- what the fuck am i doing lol
-- [TODO] - this causes a funny bug when itg fails early and then the song is skipped
local barchanges = (not iscourse) and WF.LifeBarChanges[pn][i]
or WF.LifeBarChanges[pn][i][WF.CurrentSongInCourse]
- table.insert(barchanges, {0, ts})
+ table.insert(barchanges, { 0, ts })
end
end
end
@@ -1503,7 +1512,7 @@ WF.UpdateProfilesOnEvaluation = function(hashes)
stats.SongsPlayed = stats.SongsPlayed + WF.CurrentSongInCourse
end
for i = 1, 5 do
- stats.TotalTapJudgments[i] = stats.TotalTapJudgments[i] + pss:GetTapNoteScores("TapNoteScore_W"..i)
+ stats.TotalTapJudgments[i] = stats.TotalTapJudgments[i] + pss:GetTapNoteScores("TapNoteScore_W" .. i)
end
stats.TotalTapJudgments[6] = stats.TotalTapJudgments[6] + pss:GetTapNoteScores("TapNoteScore_Miss")
local ra = pss:GetRadarActual()
@@ -1515,7 +1524,8 @@ WF.UpdateProfilesOnEvaluation = function(hashes)
stats.TotalMines[1] = stats.TotalMines[1] + pss:GetTapNoteScores("TapNoteScore_HitMine")
stats.TotalMines[2] = stats.TotalMines[2] + rv:GetValue("Mines")
if not iscourse then
- stats.LastSongPlayed = song:GetSongDir():gsub("/AdditionalSongs/","",1):gsub("/Songs/","",1):sub(1,-2)
+ stats.LastSongPlayed = song:GetSongDir():gsub("/AdditionalSongs/", "", 1):gsub("/Songs/", "", 1):sub(1,
+ -2)
end
-- loop through all potential "item stats"
@@ -1533,18 +1543,18 @@ WF.UpdateProfilesOnEvaluation = function(hashes)
local curitgclr = itgclr
local curfaplus = WF.FAPlusCount[pn]
if cind > 1 then
- local jt = {curstatsobj:GetJudgmentCount("W1"),curstatsobj:GetJudgmentCount("W2"),
- curstatsobj:GetJudgmentCount("W3"),curstatsobj:GetJudgmentCount("W4"),
- curstatsobj:GetJudgmentCount("W5"),curstatsobj:GetJudgmentCount("Miss"),
- curstatsobj:GetJudgmentCount("Held"),curstatsobj:GetJudgmentCount("LetGo"),
- curstatsobj:GetJudgmentCount("HitMine")}
+ local jt = { curstatsobj:GetJudgmentCount("W1"), curstatsobj:GetJudgmentCount("W2"),
+ curstatsobj:GetJudgmentCount("W3"), curstatsobj:GetJudgmentCount("W4"),
+ curstatsobj:GetJudgmentCount("W5"), curstatsobj:GetJudgmentCount("Miss"),
+ curstatsobj:GetJudgmentCount("Held"), curstatsobj:GetJudgmentCount("LetGo"),
+ curstatsobj:GetJudgmentCount("HitMine") }
curdp = math.floor(WF.CalculatePercentDP(jt, cursteps, player, false) * 10000)
- curitgdp = math.floor(WF.CalculatePercentDP(WF.ITGJudgmentCountsPerSongInCourse[pn][cind-1],
+ curitgdp = math.floor(WF.CalculatePercentDP(WF.ITGJudgmentCountsPerSongInCourse[pn][cind - 1],
cursteps, player, true) * 10000)
- curfaplus = WF.FAPlusCountPerSongInCourse[pn][cind-1]
+ curfaplus = WF.FAPlusCountPerSongInCourse[pn][cind - 1]
if WF.ITGFailed[pn] then
- if cind-1 < WF.ITGSongInCourseAtFail[pn] then curitgclr = "C"
- elseif cind-1 == WF.ITGSongInCourseAtFail[pn] then curitgclr = "F"
+ if cind - 1 < WF.ITGSongInCourseAtFail[pn] then curitgclr = "C"
+ elseif cind - 1 == WF.ITGSongInCourseAtFail[pn] then curitgclr = "F"
else curitgclr = nil end
end
end
@@ -1599,8 +1609,9 @@ WF.UpdateProfilesOnEvaluation = function(hashes)
end
local newgrade_itg = CalculateGradeITG(songstats)
if newgrade_itg < oldgrade_itg then
- if oldgrade_itg ~= 99 then stats.GradeCounts_ITG[oldgrade_itg] =
- stats.GradeCounts_ITG[oldgrade_itg] - 1 end
+ if oldgrade_itg ~= 99 then stats.GradeCounts_ITG[oldgrade_itg] = stats.GradeCounts_ITG[oldgrade_itg]
+ - 1
+ end
stats.GradeCounts_ITG[newgrade_itg] = stats.GradeCounts_ITG[newgrade_itg] + 1
end
for i = 1, 2 do
@@ -1625,7 +1636,7 @@ WF.UpdateProfilesOnEvaluation = function(hashes)
songstats.BestPercentDP = curdp
songstats.BestPlay.DateObtained = dateobtained
for i = 1, 5 do
- songstats.BestPlay.Judgments[i] = curstatsobj:GetJudgmentCount("TapNoteScore_W"..i)
+ songstats.BestPlay.Judgments[i] = curstatsobj:GetJudgmentCount("TapNoteScore_W" .. i)
end
songstats.BestPlay.Judgments[6] = curstatsobj:GetJudgmentCount("TapNoteScore_Miss")
songstats.BestPlay.Judgments[7] = (cind == 1) and currv:GetValue("Holds")
@@ -1641,7 +1652,7 @@ WF.UpdateProfilesOnEvaluation = function(hashes)
local bar = WF.LifeBarValues[pn][i]
local saf = (bar.ScoreAtFail ~= -1) and bar.ScoreAtFail or curdp
if cind > 1 then
- saf = (not (bar.Failed and bar.SongInCourseAtFail == cind - 1))
+ saf = (not (bar.Failed and bar.SongInCourseAtFail == cind - 1))
and bar.ScoreAtFailSongInCourse or curdp
end
songstats.BestPlay.ScoreAtLifeEmpty[i] = saf
@@ -1652,7 +1663,7 @@ WF.UpdateProfilesOnEvaluation = function(hashes)
if not iscourse then
WF.WriteDetailedHighScoreStats(pn, songstats)
else
- table.insert(wfus[pn], cind-1)
+ table.insert(wfus[pn], cind - 1)
end
end
@@ -1663,7 +1674,7 @@ WF.UpdateProfilesOnEvaluation = function(hashes)
if not iscourse then
WF.WriteDetailedHighScoreStats(pn, nil, "_ITG")
else
- table.insert(itgus[pn], cind-1)
+ table.insert(itgus[pn], cind - 1)
end
end
@@ -1710,18 +1721,18 @@ WF.UpdateProfilesOnEvaluation = function(hashes)
local curitgclr = itgclr
local curfaplus = WF.FAPlusCount[pn]
if cind > 1 then
- local jt = {curstatsobj:GetJudgmentCount("W1"),curstatsobj:GetJudgmentCount("W2"),
- curstatsobj:GetJudgmentCount("W3"),curstatsobj:GetJudgmentCount("W4"),
- curstatsobj:GetJudgmentCount("W5"),curstatsobj:GetJudgmentCount("Miss"),
- curstatsobj:GetJudgmentCount("Held"),curstatsobj:GetJudgmentCount("LetGo"),
- curstatsobj:GetJudgmentCount("HitMine")}
+ local jt = { curstatsobj:GetJudgmentCount("W1"), curstatsobj:GetJudgmentCount("W2"),
+ curstatsobj:GetJudgmentCount("W3"), curstatsobj:GetJudgmentCount("W4"),
+ curstatsobj:GetJudgmentCount("W5"), curstatsobj:GetJudgmentCount("Miss"),
+ curstatsobj:GetJudgmentCount("Held"), curstatsobj:GetJudgmentCount("LetGo"),
+ curstatsobj:GetJudgmentCount("HitMine") }
curdp = math.floor(WF.CalculatePercentDP(jt, cursteps, player, false) * 10000)
- curitgdp = math.floor(WF.CalculatePercentDP(WF.ITGJudgmentCountsPerSongInCourse[pn][cind-1],
+ curitgdp = math.floor(WF.CalculatePercentDP(WF.ITGJudgmentCountsPerSongInCourse[pn][cind - 1],
cursteps, player, true) * 10000)
- curfaplus = WF.FAPlusCountPerSongInCourse[pn][cind-1]
+ curfaplus = WF.FAPlusCountPerSongInCourse[pn][cind - 1]
if WF.ITGFailed[pn] then
- if cind-1 < WF.ITGSongInCourseAtFail[pn] then curitgclr = "C"
- elseif cind-1 == WF.ITGSongInCourseAtFail[pn] then curitgclr = "F"
+ if cind - 1 < WF.ITGSongInCourseAtFail[pn] then curitgclr = "C"
+ elseif cind - 1 == WF.ITGSongInCourseAtFail[pn] then curitgclr = "F"
else curitgclr = nil end
end
end
@@ -1748,7 +1759,7 @@ WF.UpdateProfilesOnEvaluation = function(hashes)
-- so this essentially checks if the same chart was played and play count has already incremented
curmstats.PlayCount = curmstats.PlayCount + 1
end
-
+
-- insert into high score list
local profile = PROFILEMAN:GetProfile(player)
@@ -1760,7 +1771,7 @@ WF.UpdateProfilesOnEvaluation = function(hashes)
curmr.PlayerGuid = (not isguest) and profile:GetGUID() or "None"
curmr.DateObtained = dateobtained
curmr.PercentDP = dplist[pn][cind]
- curmstats.HighScoreList[#curmstats.HighScoreList+1] = curmr
+ curmstats.HighScoreList[#curmstats.HighScoreList + 1] = curmr
table.insert(mr[pn], curmr)
-- insert into itg high score list
@@ -1771,7 +1782,7 @@ WF.UpdateProfilesOnEvaluation = function(hashes)
curitgmr.PlayerGuid = (not isguest) and profile:GetGUID() or ""
curitgmr.DateObtained = dateobtained
curitgmr.PercentDP = dplist_itg[pn][cind]
- curmstats.HighScoreList_ITG[#curmstats.HighScoreList_ITG+1] = curitgmr
+ curmstats.HighScoreList_ITG[#curmstats.HighScoreList_ITG + 1] = curitgmr
table.insert(itgmr[pn], curitgmr)
if not iscourse then
@@ -1803,7 +1814,7 @@ WF.UpdateProfilesOnEvaluation = function(hashes)
for k, v in pairs(score) do if mr[pn][cind][k] ~= v then found = false end end
if found then
if cind == 1 then rt[pn].MachineHSInd = i
- else rt[pn].MachineCourseSongHSInd[cind-1] = i end
+ else rt[pn].MachineCourseSongHSInd[cind - 1] = i end
break
end
end
@@ -1812,13 +1823,13 @@ WF.UpdateProfilesOnEvaluation = function(hashes)
for k, v in pairs(score) do if itgmr[pn][cind][k] ~= v then found = false end end
if found then
if cind == 1 then rt[pn].MachineHSInd_ITG = i
- else rt[pn].MachineCourseSongHSInd_ITG[cind-1] = i end
+ else rt[pn].MachineCourseSongHSInd_ITG[cind - 1] = i end
break
end
end
end
end
-
+
return rt
end
@@ -1831,7 +1842,7 @@ WF.CopySongStats = function(hs)
t[k] = v
elseif k == "BestFAPlusCounts" then
t[k] = {}
- for i = 1,3 do t[k][i] = v[i] end
+ for i = 1, 3 do t[k][i] = v[i] end
end
end
return t
@@ -1844,15 +1855,15 @@ WF.ImportCheck = function()
-- with the new system the UI probably doesn't need to report anything super specific
if ThemePrefs.Get("AlwaysMergeScores") then return true end
local mdir = PROFILEMAN:GetProfileDir("ProfileSlot_Machine")
- if not FILEMAN:DoesFileExist(mdir.."/MachineStats.wfm") then return true end
+ if not FILEMAN:DoesFileExist(mdir .. "/MachineStats.wfm") then return true end
if WF.MachineProfileStats and WF.MachineProfileStats.ForceImportCourses then
return true
end
local players = GAMESTATE:GetHumanPlayers()
for player in ivalues(players) do
local pn = player:sub(-1)
- local dir = PROFILEMAN:GetProfileDir("ProfileSlot_Player"..pn)
- if (dir ~= "") and (not FILEMAN:DoesFileExist(dir.."/PlayerStats.wfs")) then
+ local dir = PROFILEMAN:GetProfileDir("ProfileSlot_Player" .. pn)
+ if (dir ~= "") and (not FILEMAN:DoesFileExist(dir .. "/PlayerStats.wfs")) then
return true
end
if WF.PlayerProfileStats[pn] and WF.PlayerProfileStats[pn].ForceImportCourses then
@@ -1870,31 +1881,31 @@ WF.MergeProfileStats = function()
-- There is also now a ThemePref that will force this merge always; this is more affordable to do now
-- with the addition of a maintained hash cache #HashCash
-
+
-- check which we should import first, so that we can minimize the amount of SetStatsPrefix jawns
local mdir = PROFILEMAN:GetProfileDir("ProfileSlot_Machine")
local alwaysmerge = ThemePrefs.Get("AlwaysMergeScores")
- local importmachine = alwaysmerge or (not FILEMAN:DoesFileExist(mdir.."/MachineStats.wfm"))
+ local importmachine = alwaysmerge or (not FILEMAN:DoesFileExist(mdir .. "/MachineStats.wfm"))
if (not importmachine) and WF.MachineProfileStats and WF.MachineProfileStats.ForceImportCourses then
importmachine = true
end
local importsongsmachine = importmachine
if (importmachine) and (WF.MachineProfileStats.ForceImportCourses) and (not alwaysmerge)
- and FILEMAN:DoesFileExist(mdir.."/MachineStats.wfm") then
+ and FILEMAN:DoesFileExist(mdir .. "/MachineStats.wfm") then
importsongsmachine = false
end
local players = GAMESTATE:GetHumanPlayers()
local importplayers = {}
- local importsongsplayer = {true,true}
+ local importsongsplayer = { true, true }
for player in ivalues(players) do
local pn = tonumber(player:sub(-1))
- local dir = PROFILEMAN:GetProfileDir("ProfileSlot_Player"..pn)
- if alwaysmerge or ((dir ~= "") and (not FILEMAN:DoesFileExist(dir.."/PlayerStats.wfs")))
- or (WF.PlayerProfileStats[pn] and WF.PlayerProfileStats[pn].ForceImportCourses) then
+ local dir = PROFILEMAN:GetProfileDir("ProfileSlot_Player" .. pn)
+ if alwaysmerge or ((dir ~= "") and (not FILEMAN:DoesFileExist(dir .. "/PlayerStats.wfs")))
+ or (WF.PlayerProfileStats[pn] and WF.PlayerProfileStats[pn].ForceImportCourses) then
table.insert(importplayers, player)
- if (not alwaysmerge) and FILEMAN:DoesFileExist(dir.."/PlayerStats.wfs")
- and WF.PlayerProfileStats[pn].ForceImportCourses then
+ if (not alwaysmerge) and FILEMAN:DoesFileExist(dir .. "/PlayerStats.wfs")
+ and WF.PlayerProfileStats[pn].ForceImportCourses then
importsongsplayer[pn] = false
end
end
@@ -1939,15 +1950,15 @@ WF.ImportProfileStats = function(importsongs, importcourses, pn)
-- pn nil for machine
local stats = (not pn) and WF.MachineProfileStats or WF.PlayerProfileStats[pn]
if not stats then return end
- local profile = (not pn) and PROFILEMAN:GetMachineProfile() or PROFILEMAN:GetProfile("PlayerNumber_P"..pn)
+ local profile = (not pn) and PROFILEMAN:GetMachineProfile() or PROFILEMAN:GetProfile("PlayerNumber_P" .. pn)
if not profile then return end
local curprefix = PROFILEMAN:GetStatsPrefix()
- local scoretype = {["Exp-"] = "standard", [""] = "ITG", ["ECFA-"] = "ITG (FA+)"}
+ local scoretype = { ["Exp-"] = "standard", [""] = "ITG", ["ECFA-"] = "ITG (FA+)" }
-- status message traced to log
local name = (not pn) and "Machine" or profile:GetDisplayName()
- local statusbase = "Importing scores for profile: "..name
+ local statusbase = "Importing scores for profile: " .. name
local status = statusbase
Trace(status)
@@ -1977,10 +1988,10 @@ WF.ImportProfileStats = function(importsongs, importcourses, pn)
if hsl then
local scores = hsl:GetHighScores()
local stepsid = WF.GetItemID(song, steps)
- status = statusbase.."\nScores found for chart/course: "..stepsid
+ status = statusbase .. "\nScores found for chart/course: " .. stepsid
Trace(status)
local bestplayset = {} -- used below
-
+
for scoreind, score in ipairs(scores) do
-- first check if song stats already exists, and create it if not.
-- need to get the songstats each iteration, because rate might be different (ugh)
@@ -2006,7 +2017,7 @@ WF.ImportProfileStats = function(importsongs, importcourses, pn)
hs.PlayerGuid = "Unknown"
hs.DateObtained = tostring(score:GetDate())
hs.PercentDP = dp
- list[#list+1] = hs
+ list[#list + 1] = hs
end
else
-- for player, we need to get all the personal best stuff we can detect.
@@ -2030,7 +2041,7 @@ WF.ImportProfileStats = function(importsongs, importcourses, pn)
songstats.BestFAPlusCounts[3] = math.max(songstats.BestFAPlusCounts[3], faplus)
if newscore then
stats.TotalTapJudgments[1] = stats.TotalTapJudgments[1] + faplus
- -- we can detect a "mastery" if score is 100% and there are no W2 judgments
+ -- we can detect a "mastery" if score is 100% and there are no W2 judgments
if score:GetPercentDP() == 1 and score:GetTapNoteScore("TapNoteScore_W2") == 0 then
songstats.BestClearType = 1
songstats.BestPercentDP = 10000
@@ -2067,9 +2078,10 @@ WF.ImportProfileStats = function(importsongs, importcourses, pn)
if newscore then
for i = 1, 5 do
stats.TotalTapJudgments[i] = stats.TotalTapJudgments[i]
- + statsobj:GetJudgmentCount("W"..i)
+ + statsobj:GetJudgmentCount("W" .. i)
end
- stats.TotalTapJudgments[6] = stats.TotalTapJudgments[6] + statsobj:GetJudgmentCount("Miss")
+ stats.TotalTapJudgments[6] = stats.TotalTapJudgments[6] +
+ statsobj:GetJudgmentCount("Miss")
-- there is no way to reliably differentiate holds from rolls in terms of performance vs
-- total, so we'll just ignore those. but we can at least tally mines.
@@ -2085,7 +2097,7 @@ WF.ImportProfileStats = function(importsongs, importcourses, pn)
if not bestplayset[rate] then
local bp = songstats.BestPlay
bp.DateObtained = tostring(score:GetDate())
- for i = 1,5 do bp.Judgments[i] = statsobj:GetJudgmentCount("W"..i) end
+ for i = 1, 5 do bp.Judgments[i] = statsobj:GetJudgmentCount("W" .. i) end
bp.Judgments[6] = statsobj:GetJudgmentCount("Miss")
-- just combine holds held and rolls held into holds held
bp.Judgments[7] = statsobj:GetJudgmentCount("Held")
@@ -2096,7 +2108,7 @@ WF.ImportProfileStats = function(importsongs, importcourses, pn)
bp.LifeBarVals[3] = 0
bp.LifeBarVals[1] = (not failed) and 1000 or 0
bp.LifeBarVals[2] = (not failed) and 800 or 0
- for i = 1,3 do bp.ScoreAtLifeEmpty[i] = dp end
+ for i = 1, 3 do bp.ScoreAtLifeEmpty[i] = dp end
-- won't bother with significant mods for this
bestplayset[rate] = true
end
@@ -2107,7 +2119,7 @@ WF.ImportProfileStats = function(importsongs, importcourses, pn)
end
end
- status = statusbase.."\nDone"
+ status = statusbase .. "\nDone"
Trace(status)
-- save stats before next load (upon changing the prefix)
@@ -2119,66 +2131,68 @@ end
WF.ProfileCardLowerAF = function(pn, items)
-- items can be passed in, otherwise will come from ThemePrefs for the profile.
-- options are "SongsPlayed", "FCTiers", "FCTiersNoPerfect", "LifeBarClears", "TopGradesITG"
- if not items then items = SL["P"..pn].ActiveModifiers.ProfileCardInfo end
+ if not items then items = SL["P" .. pn].ActiveModifiers.ProfileCardInfo end
if not items then items = "SongsPlayed" end
- local af = Def.ActorFrame{}
+ local af = Def.ActorFrame {}
local iscourse = GAMESTATE:IsCourseMode()
if items == "SongsPlayed" then
- af[#af+1] = LoadFont("Common Normal")..{
+ af[#af + 1] = LoadFont("Common Normal") .. {
Text = "Current Session:",
InitCommand = function(self) self:y(4):zoom(0.8) end
}
- af[#af+1] = LoadFont("Common Normal")..{
+ af[#af + 1] = LoadFont("Common Normal") .. {
Text = string.format("%d %s%s", WF.CurrentSessionSongsPlayed[pn], (not iscourse) and "song" or "course",
(WF.CurrentSessionSongsPlayed[pn] > 1) and "s" or ""),
InitCommand = function(self) self:zoom(0.8):y(20) end
}
elseif items == "FCTiers" or items == "FCTiersNoPerfect" or items == "LifeBarClears" then
- local cto = {FCTiers = 0, FCTiersNoPerfect = 1, LifeBarClears = 4}
+ local cto = { FCTiers = 0, FCTiersNoPerfect = 1, LifeBarClears = 4 }
local p = (not iscourse) and "" or "Course"
for i = 1, 3 do
local cti = i + cto[items]
- af[#af+1] = LoadFont("Common Normal")..{
+ af[#af + 1] = LoadFont("Common Normal") .. {
Text = WF.ClearTypesShort[cti],
- InitCommand = function(self) self:zoom(0.8):diffuse(WF.ClearTypeColor(cti)):xy(-20, 14*(i-1)) end
+ InitCommand = function(self) self:zoom(0.8):diffuse(WF.ClearTypeColor(cti)):xy(-20, 14 * (i - 1)) end
}
- af[#af+1] = LoadFont("Common Normal")..{
- Text = tostring(WF.PlayerProfileStats[pn][p.."ClearTypeCounts"][cti]),
- InitCommand = function(self) self:zoom(0.8):xy(36, 14*(i-1)):horizalign("right"):maxwidth(36/0.8) end
+ af[#af + 1] = LoadFont("Common Normal") .. {
+ Text = tostring(WF.PlayerProfileStats[pn][p .. "ClearTypeCounts"][cti]),
+ InitCommand = function(self) self:zoom(0.8):xy(36, 14 * (i - 1)):horizalign("right"):maxwidth(36 / 0.8) end
}
end
elseif items == "TopGradesITG" then
- local positions = {{-34, 2}, {12, 2}, {-34, 24}, {12, 24}}
+ local positions = { { -34, 2 }, { 12, 2 }, { -34, 24 }, { 12, 24 } }
local p = (not iscourse) and "" or "Course"
for i = 1, 4 do
- af[#af+1] = LoadActor(THEME:GetPathG("", "_GradesSmall/LetterGrade.lua"), {grade = i, itg = true})..{
- OnCommand = function(self) self:zoom(0.2):xy(positions[i][1], positions[i][2]) end
- }
- af[#af+1] = LoadFont("Common Normal")..{
- Text = tostring(WF.PlayerProfileStats[pn][p.."GradeCounts_ITG"][i]),
- InitCommand = function(self) self:zoom(0.75):xy(positions[i][1] + 32, positions[i][2]+1)
- :maxwidth(20/0.75):horizalign("right") end
+ af[#af + 1] = LoadActor(THEME:GetPathG("", "_GradesSmall/LetterGrade.lua"), { grade = i, itg = true }) ..
+ {
+ OnCommand = function(self) self:zoom(0.2):xy(positions[i][1], positions[i][2]) end
+ }
+ af[#af + 1] = LoadFont("Common Normal") .. {
+ Text = tostring(WF.PlayerProfileStats[pn][p .. "GradeCounts_ITG"][i]),
+ InitCommand = function(self) self:zoom(0.75):xy(positions[i][1] + 32, positions[i][2] + 1)
+ :maxwidth(20 / 0.75):horizalign("right")
+ end
}
end
elseif items == "ECFA2021" then
-- unused now
local points = tostring(math.floor(WF.PlayerProfileStats[pn].ECFA2021ScoreList.TotalPoints))
local songs = tostring(WF.PlayerProfileStats[pn].ECFA2021ScoreList.Songs)
- af[#af+1] = LoadFont("Common Normal")..{
+ af[#af + 1] = LoadFont("Common Normal") .. {
Text = "ECFA Total",
InitCommand = function(self) self:zoom(0.8) end
}
- af[#af+1] = LoadFont("Common Normal")..{
+ af[#af + 1] = LoadFont("Common Normal") .. {
Text = points,
- InitCommand = function(self) self:zoom(0.8):y(14):maxwidth(92/0.8) end
+ InitCommand = function(self) self:zoom(0.8):y(14):maxwidth(92 / 0.8) end
}
- af[#af+1] = LoadFont("Common Normal")..{
+ af[#af + 1] = LoadFont("Common Normal") .. {
Text = "Songs Played:",
InitCommand = function(self) self:zoom(0.7):xy(-44, 29):horizalign("left") end
}
- af[#af+1] = LoadFont("Common Normal")..{
+ af[#af + 1] = LoadFont("Common Normal") .. {
Text = songs,
InitCommand = function(self) self:zoom(0.7):xy(44, 29):horizalign("right") end
}
@@ -2197,26 +2211,25 @@ function TestHashes()
for id, v in pairs(HashTest) do
if id ~= "WFVersion" then
if WF.HashCache[id] == v then
- Trace("Hashes match for ID: "..id)
+ Trace("Hashes match for ID: " .. id)
Trace(v or "[NO HASH]")
Trace(WF.HashCache[id] or "[NO HASH]")
else
if WF.HashCache[id] then
wrong = wrong + 1
- Trace("Hashes do not match for ID: "..id)
+ Trace("Hashes do not match for ID: " .. id)
Trace(v or "[NO HASH]")
Trace(WF.HashCache[id] or "[NO HASH]")
else
nochart = nochart + 1
- Trace("No chart or hash for ID: "..id)
+ Trace("No chart or hash for ID: " .. id)
end
end
end
end
- Trace("Hash test complete. "..wrong.." incorrect hashes, "..nochart.." empty hashes.")
+ Trace("Hash test complete. " .. wrong .. " incorrect hashes, " .. nochart .. " empty hashes.")
end
-
-- The following is a really dumb hacky idea, entirely to try to maintain "Last song played."
-- Firstly, we'll have a flag that signals to the theme to not do any of the WF file operations for profiles
-- if it's set while the Load/SaveProfileCustom functions run, because there is no need.
@@ -2263,7 +2276,7 @@ WF.InitHashCache = function()
if (fn) and fn ~= "" and (steps:GetStepsType():find("Dance") or steps:GetStepsType():find("Pump")) then
local id = WF.GetStepsID(song, steps)
if not WF.HashCache[id] then
- table.insert(WF.NewChartsToCache, {song, steps})
+ table.insert(WF.NewChartsToCache, { song, steps })
end
end
end
@@ -2334,6 +2347,8 @@ WF.SaveHashCache = function()
end
end
+ File.Write("/Save/Waterfall/zkldi.json", json.encode(WF.ZkldiDump))
+
local fstr = table.concat(ft, "\n")
if File.Write(path, fstr) then
Trace("Hash Cache successfully written. #HashCash")
@@ -2347,8 +2362,8 @@ WF.GetHashCacheBuildStatus = function(total)
-- if no total is passed in, the number of items in the NewChartsToCache table will be used, and then that
-- total can be passed back in
if not total then total = #WF.NewChartsToCache end
-
- local rt = {Step = "Generating hash", ChartID = "", Finished = total - #WF.NewChartsToCache, Total = total}
+
+ local rt = { Step = "Generating hash", ChartID = "", Finished = total - #WF.NewChartsToCache, Total = total }
if #WF.NewChartsToCache == 0 then
rt.Step = "Done"
WF.HashCacheBuildFinish()
@@ -2381,6 +2396,40 @@ WF.ProcessHashCacheItem = function()
hash = GetHashFromSimfileString(item[2], WF.LastMSD.MSD, WF.LastMSD.Type) or ""
end
+
+ local song = item[1]
+ local steps = item[2]
+
+ ParseChartInfo(steps, "P1")
+
+ WF.ZkldiDump[id] = {
+ title = song:GetMainTitle(),
+ artist = song:GetDisplayArtist(),
+ subtitle = song:GetDisplaySubTitle(),
+
+ chartHash = hash,
+ level = steps:GetMeter(),
+ difficulty = steps:GetDifficulty(),
+ breakdown = {
+ detailed = GenerateBreakdownText("P1", 0),
+ partiallySimplified = GenerateBreakdownText("P1", 1),
+ simplified = GenerateBreakdownText("P1", 2),
+ total = GenerateBreakdownText("P1", 3),
+ npsPerMeasure = SL.P1.Streams.NPSperMeasure,
+ notesPerMeasure = SL.P1.Streams.NotesPerMeasure,
+ },
+ tech = {
+ footswitches = SL.P1.Streams.Footswitches,
+ jacks = SL.P1.Streams.Jacks,
+ sideswitches = SL.P1.Streams.Sideswitches,
+ brackets = SL.P1.Streams.Brackets,
+ crossovers = SL.P1.Streams.Crossovers,
+ },
+ length = song:GetLastSecond(),
+ charter = steps:GetAuthorCredit(),
+ displayBPM = steps:GetDisplayBpms()
+ }
+
WF.HashCache[id] = hash
table.remove(WF.NewChartsToCache, 1)
end
@@ -2430,9 +2479,9 @@ WF.CalculateClearsAndGrades = function(stepstype, groupname, difficulty, rate, p
-- i could do all the dumb logic i did for edits in the song item file, but the idea of tracking a
-- "lamp" for a specific index of edit difficulty within a pack seems dumb and pointless to me
- if difficulty == "Difficulty_Edit" then return {WF = 0, ITG = 0} end
+ if difficulty == "Difficulty_Edit" then return { WF = 0, ITG = 0 } end
- local arg = {WF = 0, ITG = 0}
+ local arg = { WF = 0, ITG = 0 }
for song in ivalues(songs) do
local charts = song:GetStepsByStepsType(stepstype)
if charts then
@@ -2464,7 +2513,7 @@ WF.CalculateClearsAndGrades = function(stepstype, groupname, difficulty, rate, p
-- if we get here, every chart had a score of some kind. arg.WF = None CT means * for WF
-- ITG will already have 99 assigned from CalculateGradeITG if any chart was unplayed
if arg.WF == WF.ClearTypes.None then arg.WF = 99 end
-
+
WF.AddToClearsAndGrades(stepstype, groupname, difficulty, rate, pn, arg.WF, arg.ITG)
return arg
end
@@ -2480,14 +2529,14 @@ WF.PreloadClearsAndGrades = function(pn)
-- first, get all the rates we need to do this for (i feel like there should be a shortcut here but it's
-- like 4am and i'm kinda dumb)
local scores = WF.PlayerProfileStats[pn].SongStats
- local rates = {"1.0"}
+ local rates = { "1.0" }
for score in ivalues(scores) do
if (not FindInTable(score.RateMod, rates)) then table.insert(rates, score.RateMod) end
end
- local diffs =
- {"Difficulty_Beginner","Difficulty_Easy","Difficulty_Medium","Difficulty_Hard","Difficulty_Challenge"}
- local types = {"Dance_Single","Dance_Double","Pump_Single","Pump_Double"}
+ local diffs =
+ { "Difficulty_Beginner", "Difficulty_Easy", "Difficulty_Medium", "Difficulty_Hard", "Difficulty_Challenge" }
+ local types = { "Dance_Single", "Dance_Double", "Pump_Single", "Pump_Double" }
local groups = SONGMAN:GetSongGroupNames()
for rate in ivalues(rates) do
for stype in ivalues(types) do
@@ -2535,7 +2584,7 @@ WF.PullITGScoreFromGrooveStats = function(pn, hash, gsentry, steps)
if not stats then
-- no stats for 1.0; make a new one
if not steps then
- steps = GAMESTATE:GetCurrentSteps("PlayerNumber_P"..pn)
+ steps = GAMESTATE:GetCurrentSteps("PlayerNumber_P" .. pn)
end
-- don't proceed if certain things don't look right
if not steps then return end
@@ -2575,13 +2624,13 @@ end
-- (the following 2 functions were moved from WF-Scoring.lua)
WF.GetStepsID = function(song, steps)
-- this is the index for any item in the SongStats table, pertaining to any steps
- local stypeid = steps:GetStepsType():gsub("StepsType_","")
- local songid = song:GetSongDir():gsub("/AdditionalSongs/","",1):gsub("/Songs/","",1):sub(1,-2)
- local diffid = steps:GetDifficulty():gsub("Difficulty_","")
+ local stypeid = steps:GetStepsType():gsub("StepsType_", "")
+ local songid = song:GetSongDir():gsub("/AdditionalSongs/", "", 1):gsub("/Songs/", "", 1):sub(1, -2)
+ local diffid = steps:GetDifficulty():gsub("Difficulty_", "")
local ext = diffid == "Edit" and WF.GetEditIndex(song, steps) or ""
- diffid = diffid:sub(1,1)
+ diffid = diffid:sub(1, 1)
--return stypeid.."/"..songid.."/"..diffid..ext
- return table.concat({stypeid,songid,diffid..ext}, "/")
+ return table.concat({ stypeid, songid, diffid .. ext }, "/")
end
WF.GetEditIndex = function(song, steps)
@@ -2605,7 +2654,7 @@ WF.GetCourseID = function(course, trail)
if course:IsAutogen() then courseid = course:GetDisplayFullTitle() end
local diffid = ToEnumShortString(trail:GetDifficulty())
diffid = diffid:sub(1, 1)
- return table.concat({stypeid, "CRS", courseid, diffid}, "/")
+ return table.concat({ stypeid, "CRS", courseid, diffid }, "/")
end
WF.GetItemID = function(songcrs, stepstrl)
@@ -2618,7 +2667,7 @@ function LookupIdentifier(hashorid, rate)
-- OLD FUNCTION, lookup table no longer works this way, but this id is still used for detailed filenames
if IsNormalRate(rate) then return hashorid end
- return hashorid.."_"..(NormalizeRateString(rate):gsub("%.", "_"))
+ return hashorid .. "_" .. (NormalizeRateString(rate):gsub("%.", "_"))
end
function CheckLookupEntry(t, hashorid, rate)
@@ -2704,12 +2753,13 @@ function GetSignificantMods(player, steps)
-- render it insignificant. this is pretty harmless as all it will do is show the icon at eval, but
-- later on i could write a function to evaluate this (not the most complicated thing really)
local td = (not iscourse) and steps:GetTimingData()
- if (options:CMod()) and (iscourse or (not steps:IsDisplayBpmConstant()) or td:HasStops() or td:HasScrollChanges()
- or td:HasSpeedChanges() or td:HasNegativeBPMs() or td:HasWarps()) then
+ if (options:CMod()) and (
+ iscourse or (not steps:IsDisplayBpmConstant()) or td:HasStops() or td:HasScrollChanges()
+ or td:HasSpeedChanges() or td:HasNegativeBPMs() or td:HasWarps()) then
table.insert(t, "C")
end
- local turns = {"Left","Right","Mirror","Shuffle","SoftShuffle","SuperShuffle","NoMines"}
+ local turns = { "Left", "Right", "Mirror", "Shuffle", "SoftShuffle", "SuperShuffle", "NoMines" }
for turn in ivalues(turns) do
if options[turn](options) then
table.insert(t, turn)
@@ -2721,10 +2771,10 @@ function GetSignificantMods(player, steps)
end
if slmods.FAPlus ~= 0 then
- table.insert(t, string.format("FA%d", slmods.FAPlus*10000))
+ table.insert(t, string.format("FA%d", slmods.FAPlus * 10000))
end
- local what = {{"Disabled","NoBoys"},{"Extended","BigBoys"}}
+ local what = { { "Disabled", "NoBoys" }, { "Extended", "BigBoys" } }
for boy in ivalues(what) do
if math.abs(PREFSMAN:GetPreference("TimingWindowSecondsW5") - WF.GetErrorWindowVal(boy[1])) < 0.00001 then
table.insert(t, boy[2])
@@ -2739,15 +2789,18 @@ end
function IsNormalRate(rate)
return (rate == "1.0" or NormalizeRateString(rate) == "1.0")
end
+
function RateFromNumber(num)
if math.abs(1 - num) < 0.0001 then return "1.0" end
local s = tostring(num)
- if s:len() == 1 then s = s..".0" end
+ if s:len() == 1 then s = s .. ".0" end
return s
end
+
function NormalizeRateString(rate)
return RateFromNumber(tonumber(rate))
end
+
function RatesAreEqual(rate1, rate2)
return ((IsNormalRate(rate1) and IsNormalRate(rate2)) or NormalizeRateString(rate1) == NormalizeRateString(rate2))
end
@@ -2779,7 +2832,7 @@ WF.TimeString = function(hour, minute, second)
end
WF.DateTimeString = function(year, month, day, hour, minute, second)
- return WF.DateString(year, month, day).." "..WF.TimeString(hour, minute, second)
+ return WF.DateString(year, month, day) .. " " .. WF.TimeString(hour, minute, second)
end
WF.CompareDateTime = function(s1, s2)
@@ -2852,7 +2905,7 @@ mt_datetime = {
return false
end,
__eq = function(a, b)
- local chk = {"Year","Month","Day","Hour","Minute","Second"}
+ local chk = { "Year", "Month", "Day", "Hour", "Minute", "Second" }
for field in ivalues(chk) do
if a[field] ~= b[field] then return false end
end