504 lines
13 KiB
Lua
504 lines
13 KiB
Lua
-- sm-ssc fallback theme | script ring 03 | Gameplay.lua
|
|
-- [en] This file is used to store settings that should be different in each
|
|
-- game mode.
|
|
|
|
-- shakesoda calls this pump.lua
|
|
local function CurGameName()
|
|
return GAMESTATE:GetCurrentGame():GetName()
|
|
end
|
|
|
|
-- Check the active game mode against a string. Cut down typing this in metrics.
|
|
function IsGame(str) return CurGameName():lower() == str:lower() end
|
|
|
|
-- GetExtraColorThreshold()
|
|
-- [en] returns the difficulty threshold in meter
|
|
-- for songs that should be counted as boss songs.
|
|
function GetExtraColorThreshold()
|
|
local Modes = {
|
|
dance = 10,
|
|
pump = 21,
|
|
beat = 12,
|
|
kb7 = 10,
|
|
para = 10,
|
|
techno = 10,
|
|
lights = 10, -- lights shouldn't be playable
|
|
kickbox= 100, -- extra color is lame
|
|
}
|
|
return Modes[CurGameName()] or 10
|
|
end
|
|
|
|
-- GameplayMargins exists to provide a layer of backwards compatibility for
|
|
-- people using the X position metrics to set where the notefields are.
|
|
-- This makes it somewhat complex.
|
|
-- Rather than trying to understand how it works, you can simply do this:
|
|
-- (example values in parentheses)
|
|
-- 1. Decide how much space you want in the center between notefields. (80)
|
|
-- 2. Decide how much space you want on each side. (40)
|
|
-- 3. Write a simple function that just returns those numbers:
|
|
-- function GameplayMargins() return 40, 80, 40 end
|
|
-- Then the engine does the work of figuring out where each notefield should
|
|
-- be centered.
|
|
function GameplayMargins(enabled_players, styletype)
|
|
local other= {[PLAYER_1]= PLAYER_2, [PLAYER_2]= PLAYER_1}
|
|
local margins= {[PLAYER_1]= {40, 40}, [PLAYER_2]= {40, 40}}
|
|
-- Use a fake style width because calculating the real style width throws off
|
|
-- the code in the engine.
|
|
local fake_style_width= 272
|
|
-- Handle the case of a single player that is centered first because it's
|
|
-- simpler.
|
|
if Center1Player() then
|
|
local pn= enabled_players[1]
|
|
fake_style_width= 544
|
|
local center= _screen.cx
|
|
local left= center - (fake_style_width / 2)
|
|
local right= _screen.w - center - (fake_style_width / 2)
|
|
-- center margin width will be ignored.
|
|
return left, 80, right
|
|
end
|
|
local half_screen= _screen.w / 2
|
|
local left= {[PLAYER_1]= 0, [PLAYER_2]= half_screen}
|
|
for i, pn in ipairs(enabled_players) do
|
|
local edge= left[pn]
|
|
local center= THEME:GetMetric("ScreenGameplay",
|
|
"Player"..ToEnumShortString(pn)..ToEnumShortString(styletype).."X")
|
|
-- Adjust for the p2 center being on the right side.
|
|
center= center - edge
|
|
margins[pn][1]= center - (fake_style_width / 2)
|
|
margins[pn][2]= half_screen - center - (fake_style_width / 2)
|
|
if #enabled_players == 1 then
|
|
margins[other[pn]][1]= margins[pn][2]
|
|
margins[other[pn]][2]= margins[pn][1]
|
|
end
|
|
end
|
|
local left= margins[PLAYER_1][1]
|
|
local center= margins[PLAYER_1][2] + margins[PLAYER_2][1]
|
|
local right= margins[PLAYER_2][2]
|
|
return left, center, right
|
|
end
|
|
|
|
-- AllowOptionsMenu()
|
|
-- [en] returns if you are able to select options
|
|
-- on ScreenSelectMusic.
|
|
function AllowOptionsMenu()
|
|
if GAMESTATE:IsAnExtraStage() then
|
|
return false
|
|
elseif GAMESTATE:GetPlayMode() == "PlayMode_Oni" then
|
|
return false
|
|
else
|
|
return true
|
|
end
|
|
end
|
|
|
|
-- GameCompatibleModes:
|
|
-- [en] returns possible modes for ScreenSelectPlayMode
|
|
function GameCompatibleModes()
|
|
local Modes = {
|
|
dance = "Single,Double,Solo,Versus,Couple",
|
|
pump = "Single,Double,HalfDouble,Versus,Couple,Routine",
|
|
beat = "5Keys,7Keys,10Keys,14Keys,Versus5,Versus7",
|
|
kb7 = "KB7",
|
|
para = "Single",
|
|
maniax = "Single,Double,Versus",
|
|
-- todo: add versus modes for technomotion
|
|
techno = "Single4,Single5,Single8,Double4,Double5,Double8",
|
|
lights = "Single", -- lights shouldn't be playable
|
|
}
|
|
return Modes[CurGameName()]
|
|
end
|
|
|
|
local function upper_first_letter(s)
|
|
local first_letter= s:match("([a-zA-Z])")
|
|
return s:gsub(first_letter, first_letter:upper(), 1)
|
|
end
|
|
|
|
-- No more having a metric for every style for every game mode. -Kyz
|
|
function ScreenSelectStyleChoices()
|
|
local styles= GAMEMAN:GetStylesForGame(GAMESTATE:GetCurrentGame():GetName())
|
|
local choices= {}
|
|
for i, style in ipairs(styles) do
|
|
local name= style:GetName()
|
|
local cap_name= upper_first_letter(name)
|
|
-- couple-edit and threepanel don't seem like they should actually be
|
|
-- selectable. -Kyz
|
|
if name ~= "couple-edit" and name ~= "threepanel" then
|
|
choices[#choices+1]= "name," .. cap_name .. ";style," .. name ..
|
|
";text," .. cap_name .. ";screen," .. Branch.AfterSelectStyle()
|
|
end
|
|
end
|
|
return choices
|
|
end
|
|
|
|
-- No more having an xy for every style for every game mode. -Kyz
|
|
function ScreenSelectStylePositions(count)
|
|
local poses= {}
|
|
local columns= 1
|
|
local choice_height= 96
|
|
local column_x= {_screen.cx, _screen.cx + 160}
|
|
if count > 4 then
|
|
column_x[1]= _screen.cx - 160
|
|
columns= 2
|
|
end
|
|
if count > 8 then
|
|
column_x[1]= _screen.cx - 240
|
|
column_x[2]= _screen.cx
|
|
column_x[3]= _screen.cx + 240
|
|
columns= 3
|
|
end
|
|
local num_per_column= {math.ceil(count/columns), math.floor(count/columns)}
|
|
if count > 8 then
|
|
if count % 3 == 0 then
|
|
num_per_column[3]= count/columns
|
|
elseif count % 3 == 1 then
|
|
num_per_column[3]= num_per_column[2]
|
|
else
|
|
num_per_column[3]= num_per_column[1]
|
|
end
|
|
end
|
|
for c= 1, columns do
|
|
local start_y= _screen.cy - (choice_height * ((num_per_column[c] / 2)+.5))
|
|
for i= 1, num_per_column[c] do
|
|
poses[#poses+1]= {column_x[c], start_y + (choice_height * i)}
|
|
end
|
|
end
|
|
return poses
|
|
end
|
|
|
|
function SelectProfileKeys()
|
|
local sGame = CurGameName()
|
|
if sGame == "pump" then
|
|
return "Up,Down,Start,Back,Center,DownLeft,DownRight"
|
|
elseif sGame == "dance" then
|
|
return "Up,Down,Start,Back,Up2,Down2"
|
|
else
|
|
return "Up,Down,Start,Back"
|
|
end
|
|
end
|
|
|
|
-- ScoreKeeperClass:
|
|
-- [en] Determines the correct ScoreKeeper class to use.
|
|
function ScoreKeeperClass()
|
|
-- rave scorekeeper
|
|
if GAMESTATE:GetPlayMode() == 'PlayMode_Rave' then return "ScoreKeeperRave" end
|
|
if GAMESTATE:GetCurrentStyle() then
|
|
local styleType = GAMESTATE:GetCurrentStyle():GetStyleType()
|
|
if styleType == 'StyleType_TwoPlayersSharedSides' then return "ScoreKeeperShared" end
|
|
end
|
|
return "ScoreKeeperNormal"
|
|
end
|
|
|
|
-- ComboContinue:
|
|
-- [en]
|
|
function ComboContinue()
|
|
local Continue = {
|
|
dance = GAMESTATE:GetPlayMode() == "PlayMode_Oni" and "TapNoteScore_W2" or "TapNoteScore_W3",
|
|
pump = "TapNoteScore_W3",
|
|
beat = "TapNoteScore_W3",
|
|
kb7 = "TapNoteScore_W3",
|
|
para = "TapNoteScore_W4"
|
|
}
|
|
return Continue[CurGameName()] or "TapNoteScore_W3"
|
|
end
|
|
|
|
function ComboMaintain()
|
|
local Maintain = {
|
|
dance = "TapNoteScore_W3",
|
|
pump = "TapNoteScore_W4",
|
|
beat = "TapNoteScore_W3",
|
|
kb7 = "TapNoteScore_W3",
|
|
para = "TapNoteScore_W4"
|
|
}
|
|
return Maintain[CurGameName()] or "TapNoteScore_W3"
|
|
end
|
|
|
|
function ComboPerRow()
|
|
sGame = CurGameName()
|
|
if sGame == "pump" then
|
|
return true
|
|
elseif GAMESTATE:GetPlayMode() == "PlayMode_Oni" then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
function EvalUsesCheckpointsWithJudgments()
|
|
return (CurGameName() == "pump") and true or false
|
|
end
|
|
|
|
local ComboThresholds = {
|
|
dance = { Hit = 2, Miss = 2, Fail = -1 },
|
|
pump = { Hit = 4, Miss = 4, Fail = 51 },
|
|
beat = { Hit = 1, Miss = 0, Fail = -1 },
|
|
kb7 = { Hit = 1, Miss = 0, Fail = -1 },
|
|
para = { Hit = 2, Miss = 0, Fail = -1 },
|
|
maniax = { Hit = 5, Miss = 0, Fail = -1 },
|
|
-------------------------------------------
|
|
default = { Hit = 2, Miss = 2, Fail = -1 }
|
|
}
|
|
|
|
function HitCombo()
|
|
if ComboThresholds[CurGameName()] then
|
|
return ComboThresholds[CurGameName()].Hit
|
|
end
|
|
return ComboThresholds["default"].Hit
|
|
end
|
|
|
|
function MissCombo()
|
|
if ComboThresholds[CurGameName()] then
|
|
return ComboThresholds[CurGameName()].Miss
|
|
end
|
|
return ComboThresholds["default"].Miss
|
|
end
|
|
|
|
-- FailCombo:
|
|
-- [en] The combo that causes game failure.
|
|
function FailCombo()
|
|
-- ITG (dance) uses 30. Pump Pro uses 30, real Pump uses 51
|
|
if ComboThresholds[CurGameName()] then
|
|
return ComboThresholds[CurGameName()].Fail
|
|
end
|
|
return ComboThresholds["default"].Fail
|
|
end
|
|
|
|
function TwoPartSelection()
|
|
return GAMESTATE:GetCurrentGame():GetName() == "pump" and true or false
|
|
end
|
|
|
|
local RoutineSkins = {
|
|
dance = { P1 = "midi-routine-p1", P2 = "midi-routine-p2" },
|
|
pump = { P1 = "cmd-routine-p1", P2 = "cmd-routine-p2" },
|
|
kb7 = { P1 = "default", P2 = "retrobar" },
|
|
-------------------------------------------------------------
|
|
default = { P1 = "default", P2 = "default" }
|
|
}
|
|
|
|
function RoutineSkinP1()
|
|
if RoutineSkins[CurGameName()] then
|
|
return RoutineSkins[CurGameName()].P1
|
|
end
|
|
return RoutineSkins["default"].P1
|
|
end
|
|
|
|
function RoutineSkinP2()
|
|
if RoutineSkins[CurGameName()] then
|
|
return RoutineSkins[CurGameName()].P2
|
|
end
|
|
return RoutineSkins["default"].P2
|
|
end
|
|
|
|
-- todo: use tables for some of these -aj
|
|
function HoldTiming()
|
|
return IsGame("pump") and 0 or PREFSMAN:GetPreference("TimingWindowSecondsHold")
|
|
end
|
|
|
|
function ShowHoldJudgments()
|
|
return not IsGame("pump")
|
|
end
|
|
|
|
local CodeDetectorCodes = {
|
|
-- steps
|
|
PrevSteps1 = {
|
|
default = "",
|
|
dance = "Up,Up",
|
|
pump = "+UpLeft",
|
|
},
|
|
PrevSteps2 = {
|
|
default = "MenuUp,MenuUp",
|
|
dance = "MenuUp,MenuUp",
|
|
pump = "",
|
|
},
|
|
NextSteps1 = {
|
|
default = "",
|
|
dance = "Down,Down",
|
|
pump = "+UpRight",
|
|
},
|
|
NextSteps2 = {
|
|
default = "MenuDown,MenuDown",
|
|
dance = "MenuDown,MenuDown",
|
|
pump = "",
|
|
},
|
|
-- group
|
|
NextGroup = {
|
|
default = "",
|
|
dance = "MenuUp,MenuRight,MenuRight",
|
|
pump = "",
|
|
},
|
|
PrevGroup = {
|
|
default = "",
|
|
dance = "MenuUp,MenuDown,MenuUp,MenuDown",
|
|
pump = "",
|
|
},
|
|
CloseCurrentFolder = {
|
|
default = "MenuUp-MenuDown",
|
|
dance = "Up-Down",
|
|
pump = "@UpLeft-@UpRight-Center",
|
|
},
|
|
-- OptionsList
|
|
PrevOptionsList = {
|
|
default = "@MenuUp-MenuDown",
|
|
},
|
|
NextOptionsList = {
|
|
default = "@MenuDown-MenuUp",
|
|
},
|
|
-- sorts
|
|
NextSort1 = {
|
|
default = "@MenuLeft-@MenuRight-Start",
|
|
dance = "@MenuLeft-@MenuRight-Start",
|
|
pump = "@MenuLeft-@MenuRight-Start",
|
|
},
|
|
NextSort2 = {
|
|
default = "MenuLeft-MenuRight",
|
|
dance = "MenuLeft-MenuRight",
|
|
pump = "MenuLeft-MenuRight",
|
|
},
|
|
NextSort3 = {
|
|
default = "",
|
|
dance = "@Left-@Right-Start",
|
|
pump = "@DownLeft-@DownRight-Start",
|
|
},
|
|
NextSort4 = {
|
|
default = "",
|
|
dance = "Left-Right",
|
|
pump = "DownLeft-DownRight",
|
|
},
|
|
-- modemenu
|
|
ModeMenu1 = {
|
|
default = "",
|
|
dance = "Up,Down,Up,Down",
|
|
},
|
|
ModeMenu2 = {
|
|
default = "MenuUp,MenuDown,MenuUp,MenuDown",
|
|
},
|
|
-- Evaluation:
|
|
SaveScreenshot1 = {
|
|
default = "MenuLeft-MenuRight",
|
|
},
|
|
SaveScreenshot2 = {
|
|
default = "Select",
|
|
},
|
|
-- modifiers section
|
|
CancelAll = {
|
|
default = "",
|
|
dance = "Left,Right,Left,Right,Left,Right,Left,Right",
|
|
},
|
|
--- specific modifiers
|
|
Mirror = {
|
|
default = "",
|
|
dance = "",
|
|
pump = "DownRight,DownLeft,UpRight,UpLeft,DownRight,DownLeft,UpRight,UpLeft,Center",
|
|
},
|
|
Left = {
|
|
default = "",
|
|
dance = "",
|
|
},
|
|
Right = {
|
|
default = "",
|
|
dance = "",
|
|
},
|
|
Shuffle = {
|
|
default = "",
|
|
dance = "",
|
|
pump = "UpLeft,UpRight,UpLeft,UpRight,DownLeft,DownRight,DownLeft,DownRight,Center", -- random
|
|
},
|
|
SuperShuffle = {
|
|
default = "",
|
|
dance = "",
|
|
pump = "UpLeft,UpRight,DownLeft,DownRight,UpLeft,UpRight,DownLeft,DownRight,Center"
|
|
},
|
|
Reverse = {
|
|
default = "",
|
|
dance = "",
|
|
pump = "UpLeft,DownLeft,UpRight,DownRight,UpLeft,DownLeft,UpRight,DownRight,DownRight", -- drop
|
|
},
|
|
HoldNotes = {
|
|
default = "",
|
|
dance = "",
|
|
},
|
|
Mines = {
|
|
default = "",
|
|
},
|
|
Dark = {
|
|
default = "",
|
|
},
|
|
Hidden = {
|
|
default = "",
|
|
pump = "UpLeft,UpRight,DownLeft,DownRight,Center", -- vanish
|
|
},
|
|
RandomVanish = {
|
|
default = "",
|
|
},
|
|
-- boost (accel), brake (decel), stealth (nonstep)
|
|
--- next/prev modifiers
|
|
NextTransform = {
|
|
default = "",
|
|
},
|
|
NextScrollSpeed = {
|
|
default = "",
|
|
dance = "",
|
|
pump = "UpLeft,UpRight,UpLeft,UpRight,Center",
|
|
},
|
|
PreviousScrollSpeed = {
|
|
default = "",
|
|
dance = "",
|
|
pump = "UpRight,UpLeft,UpRight,UpLeft,Center",
|
|
},
|
|
NextAccel = {
|
|
default = "",
|
|
dance = "",
|
|
},
|
|
NextEffect = {
|
|
default = "",
|
|
dance = "",
|
|
},
|
|
NextAppearance = {
|
|
default = "",
|
|
dance = "",
|
|
},
|
|
NextTurn = {
|
|
default = "",
|
|
},
|
|
-- cancel all in player options
|
|
CancelAllPlayerOptions = {
|
|
default = "",
|
|
dance = "Left,Right,Left,Right,Left,Right",
|
|
},
|
|
};
|
|
|
|
function GetCodeForGame(codeName)
|
|
local gameName = string.lower(CurGameName())
|
|
local inputCode = CodeDetectorCodes[codeName]
|
|
return inputCode[gameName] or inputCode["default"]
|
|
end
|
|
|
|
local OptionsListKeys = {
|
|
PrevItem = {
|
|
pump="MenuLeft",
|
|
default="MenuUp"
|
|
},
|
|
NextItem = {
|
|
pump="MenuRight",
|
|
default="MenuDown"
|
|
}
|
|
};
|
|
|
|
function GetOptionsListMapping(name)
|
|
local sGame = string.lower(GAMESTATE:GetCurrentGame():GetName())
|
|
local map = OptionsListKeys[name]
|
|
return map[sGame] or map["default"]
|
|
end
|
|
|
|
|
|
function oitg_zoom_mode_actor()
|
|
return Def.Actor{
|
|
OnCommand= function(self)
|
|
local screen= SCREENMAN:GetTopScreen()
|
|
for i, pn in ipairs(GAMESTATE:GetEnabledPlayers()) do
|
|
local player= screen:GetChild("Player"..ToEnumShortString(pn))
|
|
if player and player.set_oitg_zoom_mode then
|
|
player:set_oitg_zoom_mode(true)
|
|
end
|
|
end
|
|
end,
|
|
}
|
|
end
|