ScoringEngine2
This commit is contained in:
@@ -1,3 +1,8 @@
|
|||||||
|
--[[DO NOT MODIFY THIS FILE.
|
||||||
|
You can add new scoring modes just by creating a different file and adding them to the
|
||||||
|
Scoring table. Replacing this file will cause additions to be lost during updates.
|
||||||
|
It's unnecessary and problematic.]]
|
||||||
|
|
||||||
--internals table
|
--internals table
|
||||||
local Shared = {};
|
local Shared = {};
|
||||||
--Special Scoring types.
|
--Special Scoring types.
|
||||||
@@ -33,477 +38,8 @@ function GetDirectRadar(player)
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
-----------------------------------------------------------
|
-----------------------------------------------------------
|
||||||
-- StepMania 3.9 (Plus) Scorings by @803832
|
--Oldschool scoring, best described as a modified 4th mix scheme
|
||||||
-- 3.9 MAX2
|
--with a little 1st mix influence
|
||||||
-- 3.9 5TH
|
|
||||||
-- 3.9Plus HYBRID
|
|
||||||
-- 3.9Plus SN
|
|
||||||
-- 3.9Plus SN2
|
|
||||||
-- note: 3.9Plus PIU Scoring cannot be implemented due to no NumTapsInRow
|
|
||||||
-- in JudgmentMessage. This is fixed in hanubeki-modified-sm-ssc revision 6c7184e7df9a:
|
|
||||||
-- http://code.google.com/r/hanubeki-modified-sm-ssc/source/detail?r=6c7184e7df9a3694649f965c2976859bb9e45963
|
|
||||||
-----------------------------------------------------------
|
|
||||||
local function isW2OrAbove(tns)
|
|
||||||
if tns == 'TapNoteScore_W1' or tns == 'TapNoteScore_W2' then
|
|
||||||
return true;
|
|
||||||
end;
|
|
||||||
return false;
|
|
||||||
end
|
|
||||||
local sm3_Steps = {0,0};
|
|
||||||
local sm3_Score = {0,0};
|
|
||||||
local sm3_CurMaxScore = {0,0};
|
|
||||||
local sm3_Combo = {0,0};
|
|
||||||
local sm3_CurMaxCombo = {0,0};
|
|
||||||
local sm3_GradePoints = {0,0};
|
|
||||||
local sm3_Bonus = {0,0};
|
|
||||||
local sm3_MaxBonus = {0,0};
|
|
||||||
|
|
||||||
r["3.9 MAX2"] = function(params, pss)
|
|
||||||
local multLookup =
|
|
||||||
{
|
|
||||||
['TapNoteScore_W1'] = 10,
|
|
||||||
['TapNoteScore_W2'] = GAMESTATE:ShowW1() and 9 or 10,
|
|
||||||
['TapNoteScore_W3'] = 5
|
|
||||||
};
|
|
||||||
setmetatable(multLookup, ZeroIfNotFound);
|
|
||||||
local radarValues = GetDirectRadar(params.Player);
|
|
||||||
local totalItems = GetTotalItems(radarValues);
|
|
||||||
-- 1+2+3+...+totalItems value/の値
|
|
||||||
local sTotal = (totalItems+1)*totalItems/2;
|
|
||||||
local steps = GAMESTATE:GetCurrentSteps(params.Player);
|
|
||||||
local meter = steps:GetMeter();
|
|
||||||
meter = clamp(meter,1,10);
|
|
||||||
|
|
||||||
-- [ja] 満点を求める
|
|
||||||
local length = 1;
|
|
||||||
if (GAMESTATE:GetCurrentSong():IsMarathon()) then
|
|
||||||
length = 3;
|
|
||||||
elseif (GAMESTATE:GetCurrentSong():IsLong()) then
|
|
||||||
length = 2;
|
|
||||||
end;
|
|
||||||
local baseScore = meter * 10000000 * length;
|
|
||||||
|
|
||||||
local sOne = baseScore/sTotal;
|
|
||||||
|
|
||||||
local p = (params.Player == 'PlayerNumber_P1') and 1 or 2;
|
|
||||||
|
|
||||||
-- [ja] スコアが0の時に初期化
|
|
||||||
if pss:GetScore()==0 then
|
|
||||||
sm3_Steps[p] = 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- [ja] 現在のステップ数
|
|
||||||
-- [ja] 地雷とHoldCheckpointsの場合は加算しない
|
|
||||||
if params.TapNoteScore ~= "TapNoteScore_HitMine" and
|
|
||||||
params.TapNoteScore ~= "TapNoteScore_AvoidMine" and
|
|
||||||
params.TapNoteScore ~= "TapNoteScore_CheckpointHit" and
|
|
||||||
params.TapNoteScore ~= "TapNoteScore_CheckpointMiss"
|
|
||||||
then
|
|
||||||
sm3_Steps[p]=sm3_Steps[p]+1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- [en] current score
|
|
||||||
-- [ja] 今回加算するスコア(W1の時)
|
|
||||||
local vScore = sOne*sm3_Steps[p];
|
|
||||||
pss:SetCurMaxScore(pss:GetCurMaxScore()+math.floor(vScore));
|
|
||||||
-- [ja] 判定によって加算量を変更
|
|
||||||
if (params.HoldNoteScore == 'HoldNoteScore_Held') then
|
|
||||||
vScore = vScore;
|
|
||||||
else
|
|
||||||
if (params.HoldNoteScore == 'HoldNoteScore_LetGo') then
|
|
||||||
vScore = 0;
|
|
||||||
else
|
|
||||||
vScore = vScore*multLookup[params.TapNoteScore]/10;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- [ja] 落ちていた場合は入るスコアが減る
|
|
||||||
if (pss:GetFailed()) then
|
|
||||||
if (params.HoldNoteScore == 'HoldNoteScore_Held') then
|
|
||||||
-- [ja] O.K.判定時は10点
|
|
||||||
sm3_Score[p] = sm3_Score[p]+10;
|
|
||||||
elseif (params.HoldNoteScore ~= 'HoldNoteScore_LetGo') then
|
|
||||||
-- [ja] O.K.でもN.G.でもない場合のスコア:
|
|
||||||
-- W1 (Marvelous): 10
|
|
||||||
-- W2 (Perfect): 9
|
|
||||||
-- W3 (Great): 5
|
|
||||||
sm3_Score[p] = sm3_Score[p]+multLookup[params.TapNoteScore];
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- [ja] 5点単位の処理がなぜかここでされる
|
|
||||||
if multLookup[params.TapNoteScore] > 0 then
|
|
||||||
sm3_Score[p] = math.floor((sm3_Score[p] + 2) / 5) * 5;
|
|
||||||
end;
|
|
||||||
else
|
|
||||||
pss:SetScore(pss:GetScore()+math.floor(vScore));
|
|
||||||
end;
|
|
||||||
|
|
||||||
if (sm3_Steps[p] == totalItems and not pss:GetFailed()) then
|
|
||||||
-- [ja] 最後の1ステップがW2以上の場合、端数を加算する
|
|
||||||
-- [ja] 端数は設定上の満点と最終ステップ時点での満点の差から求める
|
|
||||||
if (isW2OrAbove(params.TapNoteScore) or params.HoldNoteScore == 'HoldNoteScore_Held') then
|
|
||||||
pss:SetScore(pss:GetScore()+(baseScore-pss:GetCurMaxScore()));
|
|
||||||
pss:SetCurMaxScore(pss:GetCurMaxScore()+(baseScore-pss:GetCurMaxScore()));
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- TODO: Don't add combo bonus if autoplay
|
|
||||||
r["3.9 5TH"] = function(params, pss)
|
|
||||||
local multLookup =
|
|
||||||
{
|
|
||||||
['TapNoteScore_W1'] = 10,
|
|
||||||
['TapNoteScore_W2'] = GAMESTATE:ShowW1() and 9 or 10,
|
|
||||||
['TapNoteScore_W3'] = 5
|
|
||||||
};
|
|
||||||
setmetatable(multLookup, ZeroIfNotFound);
|
|
||||||
local radarValues = GetDirectRadar(params.Player);
|
|
||||||
local totalItems = GetTotalItems(radarValues);
|
|
||||||
-- 1+2+3+...+totalItems value/の値
|
|
||||||
local sTotal = (totalItems+1)*totalItems/2;
|
|
||||||
local steps = GAMESTATE:GetCurrentSteps(params.Player);
|
|
||||||
local meter = steps:GetMeter();
|
|
||||||
meter = clamp(meter,1,10);
|
|
||||||
|
|
||||||
-- [ja] 満点を求める
|
|
||||||
local length = 1;
|
|
||||||
if (GAMESTATE:GetCurrentSong():IsMarathon()) then
|
|
||||||
length = 3;
|
|
||||||
elseif (GAMESTATE:GetCurrentSong():IsLong()) then
|
|
||||||
length = 2;
|
|
||||||
end;
|
|
||||||
local baseScore = (meter * length + 1) * 5000000;
|
|
||||||
|
|
||||||
local sOne = baseScore/sTotal;
|
|
||||||
|
|
||||||
local p = (params.Player == 'PlayerNumber_P1') and 1 or 2;
|
|
||||||
|
|
||||||
-- [ja] スコアが0の時に初期化
|
|
||||||
if pss:GetScore()==0 then
|
|
||||||
sm3_Steps[p] = 0;
|
|
||||||
sm3_Score[p] = 0;
|
|
||||||
sm3_CurMaxScore[p] = 0;
|
|
||||||
sm3_Combo[p] = 0;
|
|
||||||
sm3_CurMaxCombo[p] = 0;
|
|
||||||
sm3_GradePoints[p] = 0;
|
|
||||||
sm3_Bonus[p] = 0;
|
|
||||||
sm3_MaxBonus[p] = 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- [ja] 現在のステップ数
|
|
||||||
-- [ja] 地雷とHoldCheckpointsの場合は加算しない
|
|
||||||
if params.TapNoteScore ~= "TapNoteScore_HitMine" and
|
|
||||||
params.TapNoteScore ~= "TapNoteScore_AvoidMine" and
|
|
||||||
params.TapNoteScore ~= "TapNoteScore_CheckpointHit" and
|
|
||||||
params.TapNoteScore ~= "TapNoteScore_CheckpointMiss"
|
|
||||||
then
|
|
||||||
sm3_Steps[p]=sm3_Steps[p]+1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- [en] current score
|
|
||||||
-- [ja] 今回加算するスコア(W1の時)
|
|
||||||
local vScore = sOne*sm3_Steps[p];
|
|
||||||
sm3_CurMaxScore[p] = sm3_CurMaxScore[p]+math.floor(vScore);
|
|
||||||
|
|
||||||
-- [ja] グレードの計算は5THではなくMAX2方式
|
|
||||||
local gradeWeightTable = {
|
|
||||||
['TapNoteScore_W1'] = 2,
|
|
||||||
['TapNoteScore_W2'] = 2,
|
|
||||||
['TapNoteScore_W3'] = 1,
|
|
||||||
['TapNoteScore_W5'] = -4,
|
|
||||||
['TapNoteScore_Miss'] = -8,
|
|
||||||
};
|
|
||||||
setmetatable(gradeWeightTable, ZeroIfNotFound);
|
|
||||||
|
|
||||||
-- [ja] 判定によって加算量を変更
|
|
||||||
if (params.HoldNoteScore == 'HoldNoteScore_Held') then
|
|
||||||
vScore = vScore;
|
|
||||||
sm3_GradePoints[p] = sm3_GradePoints[p] + 6;
|
|
||||||
else
|
|
||||||
if (params.HoldNoteScore == 'HoldNoteScore_LetGo') then
|
|
||||||
vScore = 0;
|
|
||||||
else
|
|
||||||
vScore = vScore*multLookup[params.TapNoteScore]/10;
|
|
||||||
sm3_GradePoints[p] = sm3_GradePoints[p] + gradeWeightTable[params.TapNoteScore];
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- [ja] コンボは自前で処理する
|
|
||||||
if not params.HoldNoteScore then
|
|
||||||
if params.TapNoteScore == 'TapNoteScore_W1' or
|
|
||||||
params.TapNoteScore == 'TapNoteScore_W2' or
|
|
||||||
(
|
|
||||||
GAMESTATE:GetPlayMode() ~= 'PlayMode_Oni' and
|
|
||||||
params.TapNoteScore == 'TapNoteScore_W3'
|
|
||||||
)
|
|
||||||
then
|
|
||||||
sm3_Combo[p] = sm3_Combo[p] + 1;
|
|
||||||
-- [ja] 地雷とHoldCheckpointsの場合はリセットしない
|
|
||||||
elseif params.TapNoteScore ~= "TapNoteScore_HitMine" and
|
|
||||||
params.TapNoteScore ~= "TapNoteScore_AvoidMine" and
|
|
||||||
params.TapNoteScore ~= "TapNoteScore_CheckpointHit" and
|
|
||||||
params.TapNoteScore ~= "TapNoteScore_CheckpointMiss"
|
|
||||||
then
|
|
||||||
sm3_Combo[p] = 0;
|
|
||||||
end;
|
|
||||||
sm3_CurMaxCombo[p] = sm3_CurMaxCombo[p] + 1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
local bonusTable =
|
|
||||||
{
|
|
||||||
['TapNoteScore_W1'] = 55,
|
|
||||||
['TapNoteScore_W2'] = 55,
|
|
||||||
['TapNoteScore_W3'] = 33
|
|
||||||
};
|
|
||||||
setmetatable(bonusTable, ZeroIfNotFound);
|
|
||||||
|
|
||||||
-- [ja] 落ちていた場合は入るスコアが減る
|
|
||||||
if (pss:GetFailed()) then
|
|
||||||
if (params.HoldNoteScore == 'HoldNoteScore_Held') then
|
|
||||||
-- [ja] O.K.判定時は10点
|
|
||||||
sm3_Score[p] = sm3_Score[p]+10;
|
|
||||||
elseif (params.HoldNoteScore ~= 'HoldNoteScore_LetGo') then
|
|
||||||
-- [ja] O.K.でもN.G.でもない場合のスコア:
|
|
||||||
-- W1 (Marvelous): 10
|
|
||||||
-- W2 (Perfect): 9
|
|
||||||
-- W3 (Great): 5
|
|
||||||
sm3_Score[p] = sm3_Score[p]+multLookup[params.TapNoteScore];
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- [ja] 5点単位の処理がなぜかここでされる
|
|
||||||
if multLookup[params.TapNoteScore] > 0 then
|
|
||||||
sm3_Score[p] = math.floor((sm3_Score[p] + 2) / 5) * 5;
|
|
||||||
end;
|
|
||||||
else
|
|
||||||
sm3_Score[p] = sm3_Score[p]+math.floor(vScore);
|
|
||||||
if (params.HoldNoteScore == 'HoldNoteScore_Held') then
|
|
||||||
sm3_Bonus[p] = sm3_Bonus[p]+55*sm3_Combo[p];
|
|
||||||
elseif (params.HoldNoteScore ~= 'HoldNoteScore_LetGo') then
|
|
||||||
sm3_Bonus[p] = sm3_Bonus[p]+bonusTable[params.TapNoteScore]*sm3_Combo[p];
|
|
||||||
end;
|
|
||||||
sm3_MaxBonus[p] = sm3_MaxBonus[p]+55*sm3_CurMaxCombo[p];
|
|
||||||
end;
|
|
||||||
|
|
||||||
if (sm3_Steps[p] == totalItems and not pss:GetFailed()) then
|
|
||||||
-- [ja] 最後の1ステップがW2以上の場合、端数を加算する
|
|
||||||
-- [ja] 端数は設定上の満点と最終ステップ時点での満点の差から求める
|
|
||||||
if (isW2OrAbove(params.TapNoteScore) or params.HoldNoteScore == 'HoldNoteScore_Held') then
|
|
||||||
sm3_Score[p] = sm3_Score[p]+(baseScore-sm3_CurMaxScore[p]);
|
|
||||||
sm3_CurMaxScore[p] = sm3_CurMaxScore[p]+(baseScore-sm3_CurMaxScore[p]);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- [ja] 5点単位の処理は5TH方式のみでされる
|
|
||||||
pss:SetScore(sm3_Score[p] - sm3_Score[p] % 5);
|
|
||||||
pss:SetCurMaxScore(sm3_CurMaxScore[p] - sm3_CurMaxScore[p] % 5);
|
|
||||||
|
|
||||||
if (sm3_Steps[p] == totalItems and not pss:GetFailed()) then
|
|
||||||
-- [ja] コンボボーナスとグレードボーナスを加算
|
|
||||||
-- [ja] 本当はリザルト画面でやりたいんだけどね
|
|
||||||
local totalTaps = radarValues:GetValue('RadarCategory_TapsAndHolds');
|
|
||||||
local totalHolds = radarValues:GetValue('RadarCategory_Holds') + radarValues:GetValue('RadarCategory_Rolls');
|
|
||||||
|
|
||||||
local gradeBonusTable = {
|
|
||||||
-- Threshold: sm3_GradePoints[p] / (totalTaps * 2 + totalHolds * 6) * 100
|
|
||||||
{ Threshold = 100, Bonus = 10000000 },
|
|
||||||
{ Threshold = 93, Bonus = 1000000 },
|
|
||||||
{ Threshold = 80, Bonus = 100000 },
|
|
||||||
{ Threshold = 65, Bonus = 10000 },
|
|
||||||
{ Threshold = 45, Bonus = 1000 },
|
|
||||||
-- [ja] 45%に達していない場合は100点とする
|
|
||||||
};
|
|
||||||
|
|
||||||
local gradeBonus = 100;
|
|
||||||
|
|
||||||
for i = 1,#gradeBonusTable do
|
|
||||||
if (sm3_GradePoints[p] / (totalTaps * 2 + totalHolds * 6) * 100 >= gradeBonusTable[i].Threshold) then
|
|
||||||
gradeBonus = gradeBonusTable[i].Bonus;
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if pss:GetFailed() then
|
|
||||||
gradeBonus = 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
pss:SetScore(pss:GetScore()+sm3_Bonus[p]+gradeBonus);
|
|
||||||
pss:SetCurMaxScore(pss:GetCurMaxScore()+sm3_MaxBonus[p]+10000000);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
r["3.9Plus HYBRID"] = function(params, pss)
|
|
||||||
local multLookup =
|
|
||||||
{
|
|
||||||
['TapNoteScore_W1'] = 10,
|
|
||||||
['TapNoteScore_W2'] = GAMESTATE:ShowW1() and 9 or 10,
|
|
||||||
['TapNoteScore_W3'] = 5
|
|
||||||
};
|
|
||||||
setmetatable(multLookup, ZeroIfNotFound);
|
|
||||||
local radarValues = GetDirectRadar(params.Player);
|
|
||||||
local totalItems = GetTotalItems(radarValues);
|
|
||||||
-- 1+2+3+...+totalItems value/の値
|
|
||||||
local sTotal = (totalItems+1)*totalItems/2;
|
|
||||||
local steps = GAMESTATE:GetCurrentSteps(params.Player);
|
|
||||||
local meter = steps:GetMeter();
|
|
||||||
meter = clamp(meter,1,10);
|
|
||||||
|
|
||||||
-- [ja] 満点を求める
|
|
||||||
local length = 1;
|
|
||||||
if (GAMESTATE:GetCurrentSong():IsMarathon()) then
|
|
||||||
length = 3;
|
|
||||||
elseif (GAMESTATE:GetCurrentSong():IsLong()) then
|
|
||||||
length = 2;
|
|
||||||
end;
|
|
||||||
local baseScore = 100000000 * length;
|
|
||||||
|
|
||||||
local sOne = baseScore/sTotal;
|
|
||||||
|
|
||||||
local p = (params.Player == 'PlayerNumber_P1') and 1 or 2;
|
|
||||||
|
|
||||||
-- [ja] スコアが0の時に初期化
|
|
||||||
if pss:GetScore()==0 then
|
|
||||||
sm3_Steps[p] = 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- [ja] 現在のステップ数
|
|
||||||
-- [ja] 地雷とHoldCheckpointsの場合は加算しない
|
|
||||||
if params.TapNoteScore ~= "TapNoteScore_HitMine" and
|
|
||||||
params.TapNoteScore ~= "TapNoteScore_AvoidMine" and
|
|
||||||
params.TapNoteScore ~= "TapNoteScore_CheckpointHit" and
|
|
||||||
params.TapNoteScore ~= "TapNoteScore_CheckpointMiss"
|
|
||||||
then
|
|
||||||
sm3_Steps[p]=sm3_Steps[p]+1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- [en] current score
|
|
||||||
-- [ja] 今回加算するスコア(W1の時)
|
|
||||||
local vScore = sOne*sm3_Steps[p];
|
|
||||||
pss:SetCurMaxScore(pss:GetCurMaxScore()+math.floor(vScore));
|
|
||||||
-- [ja] 判定によって加算量を変更
|
|
||||||
if (params.HoldNoteScore == 'HoldNoteScore_Held') then
|
|
||||||
vScore = vScore;
|
|
||||||
else
|
|
||||||
if (params.HoldNoteScore == 'HoldNoteScore_LetGo') then
|
|
||||||
vScore = 0;
|
|
||||||
else
|
|
||||||
vScore = vScore*multLookup[params.TapNoteScore]/10;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- [ja] 落ちていた場合は入るスコアが減る
|
|
||||||
if (pss:GetFailed()) then
|
|
||||||
if (params.HoldNoteScore == 'HoldNoteScore_Held') then
|
|
||||||
-- [ja] O.K.判定時は10点
|
|
||||||
pss:SetScore(pss:GetScore()+10);
|
|
||||||
elseif (params.HoldNoteScore ~= 'HoldNoteScore_LetGo') then
|
|
||||||
-- [ja] O.K.でもN.G.でもない場合のスコア:
|
|
||||||
-- W1 (Marvelous): 10
|
|
||||||
-- W2 (Perfect): 9
|
|
||||||
-- W3 (Great): 5
|
|
||||||
pss:SetScore(pss:GetScore()+multLookup[params.TapNoteScore]);
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- [ja] 5点単位の処理がなぜかここでされる
|
|
||||||
if multLookup[params.TapNoteScore] > 0 then
|
|
||||||
pss:SetScore(math.floor((pss:GetScore() + 2) / 5) * 5);
|
|
||||||
end;
|
|
||||||
else
|
|
||||||
pss:SetScore(pss:GetScore()+math.floor(vScore));
|
|
||||||
end;
|
|
||||||
|
|
||||||
if (sm3_Steps[p] == totalItems and not pss:GetFailed()) then
|
|
||||||
-- [ja] 最後の1ステップがW2以上の場合、端数を加算する
|
|
||||||
-- [ja] 端数は設定上の満点と最終ステップ時点での満点の差から求める
|
|
||||||
if (isW2OrAbove(params.TapNoteScore) or params.HoldNoteScore == 'HoldNoteScore_Held') then
|
|
||||||
pss:SetScore(pss:GetScore()+(baseScore-pss:GetCurMaxScore()));
|
|
||||||
pss:SetCurMaxScore(pss:GetCurMaxScore()+(baseScore-pss:GetCurMaxScore()));
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
r["3.9Plus SN"] = function(params, pss)
|
|
||||||
local radarValues = GetDirectRadar(params.Player);
|
|
||||||
local totalItems = GetTotalItems(radarValues);
|
|
||||||
|
|
||||||
-- [ja] 満点を求める
|
|
||||||
local length = 1;
|
|
||||||
if (GAMESTATE:GetCurrentSong():IsMarathon()) then
|
|
||||||
length = 3;
|
|
||||||
elseif (GAMESTATE:GetCurrentSong():IsLong()) then
|
|
||||||
length = 2;
|
|
||||||
end;
|
|
||||||
local baseScore = 10000000 * length;
|
|
||||||
|
|
||||||
-- [en] current score
|
|
||||||
-- [ja] 今回加算するスコア
|
|
||||||
local multLookup =
|
|
||||||
{
|
|
||||||
['TapNoteScore_W1'] = math.floor(baseScore / totalItems),
|
|
||||||
['TapNoteScore_W2'] = math.floor(baseScore / totalItems),
|
|
||||||
['TapNoteScore_W3'] = math.floor(math.floor(baseScore / 2) / totalItems)
|
|
||||||
};
|
|
||||||
setmetatable(multLookup, ZeroIfNotFound);
|
|
||||||
local vScore = multLookup[params.TapNoteScore];
|
|
||||||
pss:SetCurMaxScore(pss:GetCurMaxScore()+multLookup['TapNoteScore_W1']);
|
|
||||||
|
|
||||||
-- [ja] 判定によって加算量を変更
|
|
||||||
if (params.HoldNoteScore == 'HoldNoteScore_Held') then
|
|
||||||
vScore = multLookup['TapNoteScore_W1'];
|
|
||||||
elseif (params.HoldNoteScore == 'HoldNoteScore_LetGo') then
|
|
||||||
vScore = 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- [ja] 落ちていた場合は入るスコアが減る
|
|
||||||
if (not pss:GetFailed()) then
|
|
||||||
pss:SetScore(pss:GetScore()+math.floor(vScore));
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- [ja] 端数の処理はされていないようだ
|
|
||||||
end;
|
|
||||||
|
|
||||||
r["3.9Plus SN2"] = function(params, pss)
|
|
||||||
local radarValues = GetDirectRadar(params.Player);
|
|
||||||
local totalItems = GetTotalItems(radarValues);
|
|
||||||
|
|
||||||
-- [ja] 満点を求める
|
|
||||||
local length = 1;
|
|
||||||
if (GAMESTATE:GetCurrentSong():IsMarathon()) then
|
|
||||||
length = 3;
|
|
||||||
elseif (GAMESTATE:GetCurrentSong():IsLong()) then
|
|
||||||
length = 2;
|
|
||||||
end;
|
|
||||||
local baseScore = 1000000 * length;
|
|
||||||
|
|
||||||
-- [en] current score
|
|
||||||
-- [ja] 今回加算するスコア
|
|
||||||
local multLookup =
|
|
||||||
{
|
|
||||||
['TapNoteScore_W1'] = math.floor(baseScore / totalItems),
|
|
||||||
['TapNoteScore_W2'] = math.floor(baseScore / totalItems) - 10,
|
|
||||||
['TapNoteScore_W3'] = math.floor(math.floor(baseScore / 2) / totalItems) - 10
|
|
||||||
};
|
|
||||||
setmetatable(multLookup, ZeroIfNotFound);
|
|
||||||
local vScore = multLookup[params.TapNoteScore];
|
|
||||||
pss:SetCurMaxScore(pss:GetCurMaxScore()+multLookup['TapNoteScore_W1']);
|
|
||||||
|
|
||||||
-- [ja] 判定によって加算量を変更
|
|
||||||
if (params.HoldNoteScore == 'HoldNoteScore_Held') then
|
|
||||||
vScore = multLookup['TapNoteScore_W1'];
|
|
||||||
elseif (params.HoldNoteScore == 'HoldNoteScore_LetGo') then
|
|
||||||
vScore = 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- [ja] 落ちていた場合は入るスコアが減る
|
|
||||||
if (not pss:GetFailed()) then
|
|
||||||
pss:SetScore(pss:GetScore()+math.floor(vScore));
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- [ja] 端数の処理はされていないようだ
|
|
||||||
end;
|
|
||||||
|
|
||||||
-----------------------------------------------------------
|
|
||||||
-- Oldschool scoring, best described as a modified 4th mix
|
|
||||||
-- scheme with a little 1st mix influence
|
|
||||||
-----------------------------------------------------------
|
-----------------------------------------------------------
|
||||||
r['Oldschool'] = function(params, pss)
|
r['Oldschool'] = function(params, pss)
|
||||||
local bestPoints = 999
|
local bestPoints = 999
|
||||||
@@ -755,8 +291,7 @@ r['DDR SuperNOVA 2'] = function(params, pss)
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
-----------------------------------------------------------
|
-----------------------------------------------------------
|
||||||
-- Radar Master (disabled)
|
--Radar Master (disabled; todo: get this working with StepMania 5)
|
||||||
-- (todo: get this working with StepMania 5)
|
|
||||||
-----------------------------------------------------------
|
-----------------------------------------------------------
|
||||||
r['[SSC] Radar Master'] = function(params, pss)
|
r['[SSC] Radar Master'] = function(params, pss)
|
||||||
local masterTable = {
|
local masterTable = {
|
||||||
@@ -777,7 +312,7 @@ r['[SSC] Radar Master'] = function(params, pss)
|
|||||||
totalRadar = totalRadar + firstRadar;
|
totalRadar = totalRadar + firstRadar;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
-- two loops are needed, because we need to calculate totalRadar
|
--two loops are needed because we need to calculate totalRadar
|
||||||
--to actually calculate any part of the score
|
--to actually calculate any part of the score
|
||||||
for k,v in pairs(masterTable) do
|
for k,v in pairs(masterTable) do
|
||||||
local curPortion = pss:GetRadarActual():GetValue(k) / v;
|
local curPortion = pss:GetRadarActual():GetValue(k) / v;
|
||||||
@@ -785,7 +320,6 @@ r['[SSC] Radar Master'] = function(params, pss)
|
|||||||
end;
|
end;
|
||||||
pss:SetScore(finalScore);
|
pss:SetScore(finalScore);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
--Marvelous Incorporated Grading System (or MIGS for short)
|
--Marvelous Incorporated Grading System (or MIGS for short)
|
||||||
--basically like DP scoring with locked DP values
|
--basically like DP scoring with locked DP values
|
||||||
@@ -815,51 +349,7 @@ r['Billions DP']= function(params,pss)
|
|||||||
pss:SetScore(math.floor((pss:GetActualDancePoints()/poss)*1000000000))
|
pss:SetScore(math.floor((pss:GetActualDancePoints()/poss)*1000000000))
|
||||||
pss:SetCurMaxScore(math.floor((pss:GetCurrentPossibleDancePoints()/poss)*1000000000))
|
pss:SetCurMaxScore(math.floor((pss:GetCurrentPossibleDancePoints()/poss)*1000000000))
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- Formulas end here.
|
-- Formulas end here.
|
||||||
|
|
||||||
for v in ivalues(DisabledScoringModes) do r[v] = nil end
|
for v in ivalues(DisabledScoringModes) do r[v] = nil end
|
||||||
Scoring = r;
|
Scoring = r;
|
||||||
|
|
||||||
function UserPrefScoringMode()
|
|
||||||
local baseChoices = {}
|
|
||||||
for k,v in pairs(Scoring) do table.insert(baseChoices,k) end
|
|
||||||
if next(baseChoices) == nil then UndocumentedFeature "No scoring modes available" end
|
|
||||||
local t = {
|
|
||||||
Name = "UserPrefScoringMode";
|
|
||||||
LayoutType = "ShowAllInRow";
|
|
||||||
SelectType = "SelectOne";
|
|
||||||
OneChoiceForAllPlayers = true;
|
|
||||||
ExportOnChange = false;
|
|
||||||
Choices = baseChoices;
|
|
||||||
LoadSelections = function(self, list, pn)
|
|
||||||
if ReadPrefFromFile("UserPrefScoringMode") ~= nil then
|
|
||||||
--Load the saved scoring mode from UserPrefs.
|
|
||||||
local theValue = ReadPrefFromFile("UserPrefScoringMode");
|
|
||||||
local success = false;
|
|
||||||
|
|
||||||
--HACK: Preview 4 took out 1st and 4th scoring. Replace with a close equivalent.
|
|
||||||
if theValue == "DDR 1stMIX" or theValue == "DDR 4thMIX" then theValue = "Oldschool" end
|
|
||||||
|
|
||||||
--Search the list of scoring modes for the saved scoring mode.
|
|
||||||
for k,v in ipairs(baseChoices) do
|
|
||||||
if v == theValue then list[k] = true success = true break end
|
|
||||||
end;
|
|
||||||
|
|
||||||
--We couldn't find it, pick the first available scoring mode as a sane default.
|
|
||||||
if success == false then list[1] = true end;
|
|
||||||
else
|
|
||||||
WritePrefToFile("UserPrefScoringMode", baseChoices[1]);
|
|
||||||
list[1] = true;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
SaveSelections = function(self, list, pn)
|
|
||||||
for k,v in ipairs(list) do
|
|
||||||
if v then WritePrefToFile("UserPrefScoringMode", baseChoices[k]) break end
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
};
|
|
||||||
setmetatable( t, t );
|
|
||||||
return t;
|
|
||||||
end
|
|
||||||
|
|||||||
@@ -0,0 +1,170 @@
|
|||||||
|
--[[DO NOT MODIFY THIS FILE.
|
||||||
|
You can add new scoring modes just by creating a different file and adding them to the
|
||||||
|
ScoringModes table. Replacing this file will cause additions to be lost during updates.
|
||||||
|
It's unnecessary and problematic.]]
|
||||||
|
|
||||||
|
ScoringModes={}
|
||||||
|
|
||||||
|
local function CreateOldScoringShim(name)
|
||||||
|
return function(judg,pss,player,mode)
|
||||||
|
judg,pss,player,mode=coroutine.yield()
|
||||||
|
while true do
|
||||||
|
if mode=="update" then
|
||||||
|
Scoring[name](judg,pss)
|
||||||
|
judg,pss,player,mode=coroutine.yield(pss:GetScore(),pss:GetCurMaxScore())
|
||||||
|
elseif mode=="finalize" then
|
||||||
|
return pss:GetScore(),pss:GetCurMaxScore()
|
||||||
|
else
|
||||||
|
error("scoring shim for mode "..name.." got an unknown state.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local ZeroIfNotFound = { __index = function() return 0 end; };
|
||||||
|
|
||||||
|
function GetDirectRadar(player)
|
||||||
|
return GAMESTATE:GetCurrentSteps(player):GetRadarValues(player)
|
||||||
|
end
|
||||||
|
|
||||||
|
--The code here is an example of native modes.
|
||||||
|
|
||||||
|
--[[There are three operation modes:
|
||||||
|
init mode: The JudgmentCommand is invalid in this mode.
|
||||||
|
This mode is designed to allow you to prepare your scoring mode.
|
||||||
|
update mode: all are valid.
|
||||||
|
This lets you respond to score changes.
|
||||||
|
finalize mode: JudgementCommand invalid.
|
||||||
|
This is designed to let you give score bonuses.
|
||||||
|
]]
|
||||||
|
--[[
|
||||||
|
ScoringModes["Oldschool"]=function(judg,pss,player,mode)
|
||||||
|
local tscore = 0
|
||||||
|
local tmaxscore = 1000000000
|
||||||
|
local possibilities= {
|
||||||
|
['TapNoteScore_W1']=999,
|
||||||
|
['TapNoteScore_W2']=IsW1Allowed('TapNoteScore_W2') and 888 or 999,
|
||||||
|
['TapNoteScore_W3']=777,
|
||||||
|
['TapNoteScore_W4']=555,
|
||||||
|
['TapNoteScore_W5']=111,
|
||||||
|
};
|
||||||
|
assert(mode=="init","issues")
|
||||||
|
setmetatable(possibilities, {__index=function() return 0 end;});
|
||||||
|
judg,pss,player,mode = coroutine.yield()
|
||||||
|
--holy crap it's a state machine i guess!
|
||||||
|
while true do
|
||||||
|
if mode=="update" then
|
||||||
|
tscore=tscore+((pss:GetCurrentCombo()*111)^1.1)+ possibilities[judg.TapNoteScore] + (judg.HoldNoteScore == 'HoldNoteScore_Held' and 777 or 0)
|
||||||
|
judg,pss,player,mode = coroutine.yield(tscore,tmaxscore)
|
||||||
|
end
|
||||||
|
if mode=="finalize" then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return tscore,tmaxscore
|
||||||
|
end
|
||||||
|
|
||||||
|
ScoringModes['DDRMAX']=function(judge,pss,player,mode)
|
||||||
|
--[en] in init mode, you start here. judge will be nil.
|
||||||
|
--[jp]
|
||||||
|
local multLookup = {
|
||||||
|
TapNoteScore_W1=10,
|
||||||
|
TapNoteScore_W2=10,
|
||||||
|
TapNoteScore_W3=5 }
|
||||||
|
local notesToIgnore = {
|
||||||
|
TapNoteScore_CheckpointHit=true,
|
||||||
|
TapNoteScore_CheckpointMiss=true,
|
||||||
|
TapNoteScore_HitMine=true,
|
||||||
|
TapNoteScore_AvoidMine=true,
|
||||||
|
TapNoteScore_None=true}
|
||||||
|
local radarCategoriesAndBonuses={
|
||||||
|
RadarCategory_Stream=20000000,
|
||||||
|
RadarCategory_Air=10000000,
|
||||||
|
RadarCategory_Voltage=10000000,
|
||||||
|
RadarCategory_Chaos=10000000,
|
||||||
|
RadarCategory_Freeze=10000000}
|
||||||
|
setmetatable(multLookup,ZeroIfNotFound)
|
||||||
|
local numNoteObjects = GetDirectRadar(player):GetValue('RadarCategory_TapsAndHolds')
|
||||||
|
local base = 5000000
|
||||||
|
local curstep = 0
|
||||||
|
local score = 0
|
||||||
|
local bestscore = 0
|
||||||
|
local s = numNoteObjects<1 and 0 or ((numNoteObjects/2)*(1+numNoteObjects))
|
||||||
|
--[en] coroutine.yield() acts somewhat like return, but when the function is run by UpdateScoreKeepers() it will start here.
|
||||||
|
--[jp] xxx
|
||||||
|
judge,pss,player,mode = coroutine.yield()
|
||||||
|
--[en] a while loop is only one way to make the mode selection system, but it's probably the easiest.
|
||||||
|
--ideally, this would just be 'while mode=="update" do', with finalize stuff after it,
|
||||||
|
--but I had written the code already when I thought of that.
|
||||||
|
--[jp] xxx
|
||||||
|
while true do
|
||||||
|
--update mode code
|
||||||
|
if mode == "update" then
|
||||||
|
--[en] this filters out holds and spurious judgments. DDRMAX ignores holds for scoring purposes.
|
||||||
|
--[jp] xxx
|
||||||
|
if (not notesToIgnore[judge.TapNoteScore]) and judge.HoldNoteScore==nil then
|
||||||
|
curstep=curstep+1
|
||||||
|
if curstep>numNoteObjects then error "is bery bad" end
|
||||||
|
score=score+(pss:GetFailed() and 1 or (multLookup[judge.TapNoteScore]*math.floor(base/s)*curstep))+((curstep==numNoteObjects and pss:FullComboOfScore('TapNoteScore_W2')) and (10*(base-(math.floor(base/s)*numNoteObjects))) or 0)
|
||||||
|
bestscore = (curstep==numNoteObjects and 50000000 or bestscore+(10*math.floor(base/s)*curstep))
|
||||||
|
end
|
||||||
|
judge,pss,player,mode=coroutine.yield(score,bestscore)
|
||||||
|
end
|
||||||
|
if mode == "finalize" then
|
||||||
|
--[en] this code would work, but SM5 behavior prevents it from doing anything. it should give the groove radar bonuses.
|
||||||
|
--[jp] xyz
|
||||||
|
local actradar = pss:GetRadarActual()
|
||||||
|
local possradar = pss:GetRadarPossible()
|
||||||
|
for k,v in pairs(radarCategoriesAndBonuses) do
|
||||||
|
local thispossradar=possradar:GetValue(k)
|
||||||
|
if thispossradar>0 then
|
||||||
|
score=score+math.floor((actradar:GetValue(k)/thispossradar)*thispossradar*v)
|
||||||
|
bestscore=bestscore+(thispossradar*v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return score,bestscore
|
||||||
|
end]]
|
||||||
|
|
||||||
|
for k,v in pairs(Scoring) do
|
||||||
|
if ScoringModes[k] == nil then
|
||||||
|
ScoringModes[k] = CreateOldScoringShim(k)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function UserPrefScoringMode()
|
||||||
|
local baseChoices = {}
|
||||||
|
for k,v in pairs(ScoringModes) do table.insert(baseChoices,k) end
|
||||||
|
if next(baseChoices) == nil then UndocumentedFeature "No scoring modes available" end
|
||||||
|
local t = {
|
||||||
|
Name = "UserPrefScoringMode";
|
||||||
|
LayoutType = "ShowAllInRow";
|
||||||
|
SelectType = "SelectOne";
|
||||||
|
OneChoiceForAllPlayers = true;
|
||||||
|
ExportOnChange = false;
|
||||||
|
Choices = baseChoices;
|
||||||
|
LoadSelections = function(self, list, pn)
|
||||||
|
if ReadPrefFromFile("UserPrefScoringMode") ~= nil then
|
||||||
|
--Load the saved scoring mode from UserPrefs.
|
||||||
|
local theValue = ReadPrefFromFile("UserPrefScoringMode");
|
||||||
|
local success = false;
|
||||||
|
--HACK: Preview 4 took out 1st and 4th scoring. Replace with a close equivalent.
|
||||||
|
if theValue == "DDR 1stMIX" or theValue == "DDR 4thMIX" then theValue = "Oldschool" end
|
||||||
|
--Search the list of scoring modes for the saved scoring mode.
|
||||||
|
for k,v in ipairs(baseChoices) do if v == theValue then list[k] = true success = true break end end;
|
||||||
|
--We couldn't find it, pick the first available scoring mode as a sane default.
|
||||||
|
if success == false then list[1] = true end;
|
||||||
|
else
|
||||||
|
WritePrefToFile("UserPrefScoringMode", baseChoices[1]);
|
||||||
|
list[1] = true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
SaveSelections = function(self, list, pn)
|
||||||
|
for k,v in ipairs(list) do if v then WritePrefToFile("UserPrefScoringMode", baseChoices[k]) break end end;
|
||||||
|
end;
|
||||||
|
};
|
||||||
|
setmetatable( t, t );
|
||||||
|
return t;
|
||||||
|
end
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
--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
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
if not GAMESTATE:IsCourseMode() then
|
||||||
|
FinalizeScoreKeepers()
|
||||||
|
end
|
||||||
|
|
||||||
local function GraphDisplay( pn )
|
local function GraphDisplay( pn )
|
||||||
local t = Def.ActorFrame {
|
local t = Def.ActorFrame {
|
||||||
Def.GraphDisplay {
|
Def.GraphDisplay {
|
||||||
|
|||||||
@@ -215,8 +215,7 @@ if( not GAMESTATE:IsCourseMode() ) then
|
|||||||
params.TapNoteScore ~= 'TapNoteScore_Invalid' and
|
params.TapNoteScore ~= 'TapNoteScore_Invalid' and
|
||||||
params.TapNoteScore ~= 'TapNoteScore_None'
|
params.TapNoteScore ~= 'TapNoteScore_None'
|
||||||
then
|
then
|
||||||
Scoring[GetUserPref("UserPrefScoringMode")](params,
|
UpdateScoreKeepers(params)
|
||||||
STATSMAN:GetCurStageStats():GetPlayerStageStats(params.Player))
|
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -77,4 +77,10 @@ t[#t+1] = Def.ActorFrame {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
--Get scoring ready.
|
||||||
|
if not GAMESTATE:IsCourseMode() then
|
||||||
|
InitScoringModes((GAMESTATE:IsSideJoined(PLAYER_1) and GetUserPref("UserPrefScoringMode")),
|
||||||
|
(GAMESTATE:IsSideJoined(PLAYER_2) and GetUserPref("UserPrefScoringMode"))
|
||||||
|
end
|
||||||
|
|
||||||
return t
|
return t
|
||||||
Reference in New Issue
Block a user