118 lines
3.9 KiB
Lua
118 lines
3.9 KiB
Lua
--ScoringEngine2 by FSX v1.41
|
|
--essentially a really chunky layer to make SetScore elegant(ish)
|
|
--arguments for scorekeepers: JudgmentMessageCommand,PlayerStageStats,PlayerNumber,State
|
|
--[[changelog
|
|
v1.41 6 May 2012
|
|
*Not really sure.
|
|
*Included in SM5 for alpha 3.
|
|
v1.4 18 Apr 2012
|
|
*Support for judgment filtering.
|
|
*Minor changes.
|
|
*First public release (in SE2 Dev Kit) (didn't happen)
|
|
v1.3 17 Apr 2012
|
|
*First complete release.
|
|
*Error reporting in FinalizeScoreKeepers()
|
|
*Bug fixes.]]
|
|
--scoring modes written for the old ad-hoc system don't work, but don't cause crashes either.
|
|
--SM5 has some glue code for them, though
|
|
local stageKey = nil
|
|
local ReadiedScoreKeepers = {}
|
|
local JudgmentFilters = {}
|
|
|
|
local function CoroutineIsGood(cr)
|
|
return coroutine.status(cr)=="suspended"
|
|
end
|
|
|
|
function InitScoreKeepers(p1Mode, p2Mode)
|
|
local newStgK = {pcall(GameState.GetStageSeed,GAMESTATE)}
|
|
assert(newStgK[1], "it's too early to initialize the ScoreKeepers, the GameState isn't ready yet")
|
|
if newStgK[2] == stageKey then
|
|
Log "[InitScoreKeepers] unnecessary call"
|
|
return true
|
|
end
|
|
ReadiedScoreKeepers={}
|
|
JudgmentFilters={}
|
|
stageKey = newStgK
|
|
local intab = {}
|
|
if p1Mode ~= nil then
|
|
intab.P1 = p1Mode
|
|
end
|
|
if p2Mode ~= nil then
|
|
intab.P2 = p2Mode
|
|
end
|
|
assert(next(intab), "InitScoreKeepers didn't get any args")
|
|
for k,v in pairs(intab) do
|
|
if not ScoringModes[v] then
|
|
--SPOILER: UndocumentedFeature crashes the game intentionally.
|
|
UndocumentedFeature(k.."'s scoring mode \""..v.."\" doesn't exist.")
|
|
end
|
|
ReadiedScoreKeepers[k] = coroutine.create(ScoringModes[v])
|
|
--call each scoring mode one time in init mode
|
|
checks={coroutine.resume(ReadiedScoreKeepers[k],nil,STATSMAN:GetCurStageStats():GetPlayerStageStats("PlayerNumber_"..k), "PlayerNumber_"..k, "init")}
|
|
if not CoroutineIsGood(ReadiedScoreKeepers[k]) then SCREENMAN:SystemMessage("scoring init error: "..checks[2]) return false end
|
|
--very very very very safe filtering rule load code
|
|
if type(checks[2])=="table" then
|
|
if type(checks[2][1])..type(checks[2][2]) == "tabletable" then
|
|
local isGood=false
|
|
local tapscan = Enum.Reverse(TapNoteScore)
|
|
local holdscan = Enum.Reverse(HoldNoteScore)
|
|
local finaltable = {{},{}}
|
|
for i=1,2 do
|
|
for k,v in pairs(checks[2][i]) do
|
|
finaltable[i][v]=true
|
|
if (not (i==2 and holdscan[v] or tapscan[v])) or v==nil then isGood=false break end
|
|
isGood=true
|
|
end
|
|
if not isGood then break end
|
|
end
|
|
if isGood then
|
|
JudgmentFilters[k]=finaltable
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function UpdateScoreKeepers(JMC)
|
|
assert(JMC,"pass args, please")
|
|
runplayer = ToEnumShortString(JMC.Player)
|
|
if ReadiedScoreKeepers[runplayer] then
|
|
if JudgmentFilters[runplayer] and (JudgmentFilters[runplayer][1][JMC.TapNoteScore] or JudgmentFilters[runplayer][2][JMC.HoldNoteScore]) then
|
|
return true
|
|
end
|
|
local pss = STATSMAN:GetCurStageStats():GetPlayerStageStats(JMC.Player)
|
|
local newscores = {coroutine.resume(ReadiedScoreKeepers[runplayer],JMC,pss,JMC.Player,"update")}
|
|
if CoroutineIsGood(ReadiedScoreKeepers[runplayer]) then
|
|
pss:SetScore(newscores[2])
|
|
pss:SetCurMaxScore(newscores[3])
|
|
return true
|
|
else
|
|
SCREENMAN:SystemMessage("scoring update error: "..newscores[2])
|
|
ReadiedScoreKeepers[runplayer]=nil
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
|
|
function FinalizeScoreKeepers()
|
|
for k,v in pairs(ReadiedScoreKeepers) do
|
|
local pss = STATSMAN:GetCurStageStats():GetPlayerStageStats("PlayerNumber_"..k)
|
|
local newscores = {coroutine.resume(v,nil,pss,"PlayerNumber_"..k,"finalize")}
|
|
local status = coroutine.status(v)
|
|
--kill the scorekeeper now, we don't need it again
|
|
ReadiedScoreKeepers[k] = nil
|
|
if status=="dead" then
|
|
if newscores[1]==true then
|
|
pss:SetScore(newscores[2])
|
|
pss:SetCurMaxScore(newscores[3])
|
|
else
|
|
SCREENMAN:SystemMessage("scoring finalize error: "..newscores[2])
|
|
return false
|
|
end
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end |