This commit is contained in:
Jonathan Payne
2012-07-06 11:58:17 -07:00
25 changed files with 12547 additions and 11284 deletions
+26
View File
@@ -8,6 +8,32 @@ ________________________________________________________________________________
StepMania 5.0 ???? ?? | 20120???
--------------------------------------------------------------------------------
2012/07/06
----------
* [ScoreDisplayRave] Add FrameBase and FrameOver to the metrics. [AJ]
2012/07/05
----------
* [ScreenRanking] Added "NextPage" command. "SwitchPage" command is
now "SwitchedPage". [AJ]
* [ScreenRanking] Don't clobber alpha values when applying colors in SetPage. [AJ]
2012/07/03
----------
* [ScreenHowToPlay] Actually shows notes again. [AJ]
* [ScreenGameplay] When ShowLifeMeterForDisabledPlayers is true, don't fill up
life in the meter for the disabled player. (LifeMeterBar only) [AJ]
2012/07/02
----------
* [ScreenHowToPlay] Run InitCommand on Characters if enabled. [AJ]
* [RageUtil] Add detection of ".hg" to StripCvsAndSvn. [AJ]
2012/06/27
----------
* [SongManager] Ending a group's name in PreferredSongs with "/*" will now load
all songs from that group automatically. [AJ]
2012/06/21
----------
* [ProfileManager] Added GetPlayerName(pn) Lua binding. [AJ]
+2
View File
@@ -1732,6 +1732,8 @@ Edit/Share=Edycja
Exit=Wyjście
Game Start=Start
Jukebox=Odtwarzacz
Report Bug=Zgłoś błąd!
Chat on IRC=Dyskutuj na IRC!
Select Game=Wybór trybu gry
Theme=Motyw graficzny
Credits=Autorzy
@@ -1,173 +1,173 @@
#TITLE:Sync;
#SUBTITLE:;
#ARTIST:Unknown artist;
#TITLETRANSLIT:;
#SUBTITLETRANSLIT:;
#ARTISTTRANSLIT:;
#GENRE:;
#CREDIT:;
#BANNER:;
#BACKGROUND:;
#LYRICSPATH:;
#CDTITLE:;
#MUSIC:_sync music.ogg;
#OFFSET:-0.012;
#SAMPLESTART:0.000;
#SAMPLELENGTH:12.000;
#SELECTABLE:YES;
#BPMS:0.000=132.000;
#STOPS:;
#BGCHANGES:;
#KEYSOUNDS:;
#NOTEDATA:;
#STEPSTYPE:dance-single:;
#DESCRIPTION:blank;
#DIFFICULTY:Beginner;
#METER:1;
#RADARVALUES:0.302,0.205,0.000,0.000,0.000;
#BPMS:0.000=132.000;
#OFFSET:-0.012;
#NOTES:
// measure 1
0000
, // measure 2
1000
0001
1000
0001
1000
0001
1000
0001
, // measure 3
1000
0001
1000
0001
1000
0001
1000
0001
, // measure 4
1000
0001
1000
0001
1000
0001
1000
0001
, // measure 5
1000
0001
1000
0001
1000
0001
1000
0001
, // measure 6
1000
0001
1000
0001
1000
0001
1000
0001
, // measure 7
1000
0001
1000
0001
1000
0001
1000
0001
, // measure 8
1000
0001
1000
0001
1000
0001
1000
0001
;
#NOTEDATA:;
#STEPSTYPE:pump-single;
#DESCRIPTION:blank;
#DIFFICULTY:Beginner;
#METER:1;
#RADARVALUES:0.302,0.205,0.000,0.000,0.000;
#BPMS:0.000=132.000;
#OFFSET:-0.012;
#NOTES:
// measure 1
00000
, // measure 2
10000
00001
10000
00001
10000
00001
10000
00001
, // measure 3
10000
00001
10000
00001
10000
00001
10000
00001
, // measure 4
10000
00001
10000
00001
10000
00001
10000
00001
, // measure 5
10000
00001
10000
00001
10000
00001
10000
00001
, // measure 6
10000
00001
10000
00001
10000
00001
10000
00001
, // measure 7
10000
00001
10000
00001
10000
00001
10000
00001
, // measure 8
10000
00001
10000
00001
10000
00001
10000
00001
;
#TITLE:Sync;
#SUBTITLE:;
#ARTIST:Unknown artist;
#TITLETRANSLIT:;
#SUBTITLETRANSLIT:;
#ARTISTTRANSLIT:;
#GENRE:;
#CREDIT:;
#BANNER:;
#BACKGROUND:;
#LYRICSPATH:;
#CDTITLE:;
#MUSIC:_sync music.ogg;
#OFFSET:-0.025;
#SAMPLESTART:0.000;
#SAMPLELENGTH:12.000;
#SELECTABLE:YES;
#BPMS:0.000=132.027;
#STOPS:;
#BGCHANGES:;
#KEYSOUNDS:;
#NOTEDATA:;
#STEPSTYPE:dance-single;
#DESCRIPTION:blank;
#DIFFICULTY:Beginner;
#METER:1;
#RADARVALUES:0.302,0.205,0.000,0.000,0.000;
#BPMS:0.000=132.027;
#OFFSET:-0.025;
#NOTES:
// measure 1
0000
, // measure 2
1000
0001
1000
0001
1000
0001
1000
0001
, // measure 3
1000
0001
1000
0001
1000
0001
1000
0001
, // measure 4
1000
0001
1000
0001
1000
0001
1000
0001
, // measure 5
1000
0001
1000
0001
1000
0001
1000
0001
, // measure 6
1000
0001
1000
0001
1000
0001
1000
0001
, // measure 7
1000
0001
1000
0001
1000
0001
1000
0001
, // measure 8
1000
0001
1000
0001
1000
0001
1000
0001
;
#NOTEDATA:;
#STEPSTYPE:pump-single;
#DESCRIPTION:blank;
#DIFFICULTY:Beginner;
#METER:1;
#RADARVALUES:0.302,0.205,0.000,0.000,0.000;
#BPMS:0.000=132.027;
#OFFSET:-0.025;
#NOTES:
// measure 1
00000
, // measure 2
10000
00001
10000
00001
10000
00001
10000
00001
, // measure 3
10000
00001
10000
00001
10000
00001
10000
00001
, // measure 4
10000
00001
10000
00001
10000
00001
10000
00001
, // measure 5
10000
00001
10000
00001
10000
00001
10000
00001
, // measure 6
10000
00001
10000
00001
10000
00001
10000
00001
, // measure 7
10000
00001
10000
00001
10000
00001
10000
00001
, // measure 8
10000
00001
10000
00001
10000
00001
10000
00001
;
+350 -349
View File
@@ -1,349 +1,350 @@
-- 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() == str 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
}
return Modes[CurGameName()]
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",
-- todo: add versus modes for technomotion
techno = "Single4,Single5,Single8,Double4,Double5,Double8",
lights = "Single" -- lights shouldn't be playable
}
return Modes[CurGameName()]
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()]
end
function ComboMaintain()
local Maintain = {
dance = "TapNoteScore_W3",
pump = "TapNoteScore_W4",
beat = "TapNoteScore_W3",
kb7 = "TapNoteScore_W3",
para = "TapNoteScore_W4"
}
return Maintain[CurGameName()]
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 },
-------------------------------------------
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
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",
},
-- 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 = "Up,Left,Right,Left,Right",
pump = "DownRight,DownLeft,UpRight,UpLeft,DownRight,DownLeft,UpRight,UpLeft,Center",
},
Left = {
default = "",
dance = "Up,Down,Right,Left",
},
Right = {
default = "",
dance = "Up,Down,Left,Right",
},
Shuffle = {
default = "",
dance = "Down,Up,Down,Up",
pump = "UpLeft,UpRight,UpLeft,UpRight,DownLeft,DownRight,DownLeft,DownRight,Center", -- random
},
SuperShuffle = {
default = "",
dance = "Down,Up,Left,Right",
pump = "UpLeft,UpRight,DownLeft,DownRight,UpLeft,UpRight,DownLeft,DownRight,Center"
},
Reverse = {
default = "",
dance = "Down,Left,Right,Left,Right",
pump = "UpLeft,DownLeft,UpRight,DownRight,UpLeft,DownLeft,UpRight,DownRight,DownRight", -- drop
},
HoldNotes = {
default = "",
dance = "Right,Left,Down,Up",
},
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 = "Up,Left,Down,Left,Up",
pump = "UpLeft,UpRight,UpLeft,UpRight,Center",
},
PreviousScrollSpeed = {
default = "",
dance = "Down,Right,Up,Right,Down",
pump = "UpRight,UpLeft,UpRight,UpLeft,Center",
},
NextAccel = {
default = "",
dance = "Left,Right,Down,Up",
},
NextEffect = {
default = "",
dance = "Left,Down,Right",
},
NextAppearance = {
default = "",
dance = "Left,Up,Right",
},
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
-- 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() == str 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
}
return Modes[CurGameName()]
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",
-- todo: add versus modes for technomotion
techno = "Single4,Single5,Single8,Double4,Double5,Double8",
lights = "Single" -- lights shouldn't be playable
}
return Modes[CurGameName()]
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()]
end
function ComboMaintain()
local Maintain = {
dance = "TapNoteScore_W3",
pump = "TapNoteScore_W4",
beat = "TapNoteScore_W3",
kb7 = "TapNoteScore_W3",
para = "TapNoteScore_W4"
}
return Maintain[CurGameName()]
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
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",
},
-- 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 = "Up,Left,Right,Left,Right",
pump = "DownRight,DownLeft,UpRight,UpLeft,DownRight,DownLeft,UpRight,UpLeft,Center",
},
Left = {
default = "",
dance = "Up,Down,Right,Left",
},
Right = {
default = "",
dance = "Up,Down,Left,Right",
},
Shuffle = {
default = "",
dance = "Down,Up,Down,Up",
pump = "UpLeft,UpRight,UpLeft,UpRight,DownLeft,DownRight,DownLeft,DownRight,Center", -- random
},
SuperShuffle = {
default = "",
dance = "Down,Up,Left,Right",
pump = "UpLeft,UpRight,DownLeft,DownRight,UpLeft,UpRight,DownLeft,DownRight,Center"
},
Reverse = {
default = "",
dance = "Down,Left,Right,Left,Right",
pump = "UpLeft,DownLeft,UpRight,DownRight,UpLeft,DownLeft,UpRight,DownRight,DownRight", -- drop
},
HoldNotes = {
default = "",
dance = "Right,Left,Down,Up",
},
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 = "Up,Left,Down,Left,Up",
pump = "UpLeft,UpRight,UpLeft,UpRight,Center",
},
PreviousScrollSpeed = {
default = "",
dance = "Down,Right,Up,Right,Down",
pump = "UpRight,UpLeft,UpRight,UpLeft,Center",
},
NextAccel = {
default = "",
dance = "Left,Right,Down,Up",
},
NextEffect = {
default = "",
dance = "Left,Down,Right",
},
NextAppearance = {
default = "",
dance = "Left,Up,Right",
},
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
+21 -2
View File
@@ -1322,6 +1322,24 @@ LevelP2Y=
LevelP2OnCommand=
LevelP2OffCommand=
FrameBaseP1X=
FrameBaseP1Y=
FrameBaseP1OnCommand=
FrameBaseP1OffCommand=
FrameBaseP2X=
FrameBaseP2Y=
FrameBaseP2OnCommand=
FrameBaseP2OffCommand=
FrameOverP1X=
FrameOverP1Y=
FrameOverP1OnCommand=
FrameOverP1OffCommand=
FrameOverP2X=
FrameOverP2Y=
FrameOverP2OnCommand=
FrameOverP2OffCommand=
[ScoreKeeperRave]
AttackDurationSeconds=3.0
@@ -3822,7 +3840,7 @@ ShowCreditDisplay=false
ShowStyleIcon=false
InvertScrollSpeedButtons=false
TimerSeconds=-1
EditModifiers=""
EditModifiers="no reverse"
EditHelpX=SCREEN_LEFT+4
EditHelpY=SCREEN_TOP+16
EditHelpOnCommand=halign,0;valign,0;zoom,0.5;shadowlength,1
@@ -3923,7 +3941,7 @@ ShowStyleIcon=false
LineNames="1,2,3,4,5,6,R,7,8,9,10,Attacks,11,12,13,14,15,16"
# uses legacy speed line
Line1="lua,SpeedMods()"
Line1="list,Speed"
Line2="list,Accel"
Line3="list,Effect"
Line4="list,Appearance"
@@ -4457,6 +4475,7 @@ Class="ScreenAttract"
NextScreen="ScreenInit"
PrevScreen="ScreenInit"
TimerSeconds=3600
TimerStealth=true
ShowCreditDisplay=false
[ScreenTitleJoin]
@@ -11,11 +11,11 @@
#LYRICSPATH:;
#CDTITLE:;
#MUSIC:_gameplay sync music.ogg;
#OFFSET:-0.012;
#OFFSET:-0.025;
#SAMPLESTART:0.000;
#SAMPLELENGTH:12.000;
#SELECTABLE:YES;
#BPMS:0.000=132.000;
#BPMS:0.000=132.027;
#STOPS:;
#BGCHANGES:;
#KEYSOUNDS:;
+1032
View File
File diff suppressed because it is too large Load Diff
+93
View File
@@ -0,0 +1,93 @@
// Adapted from http://www.codeproject.com/KB/files/zip_utils.aspx
#ifndef CreateZip_H
#define CreateZip_H
// ZIP functions -- for creating zip files
// This file is a repackaged form of the Info-Zip source code available
// at www.info-zip.org. The original copyright notice may be found in
// zip.cpp. The repackaging was done by Lucian Wischik to simplify and
// extend its use in Windows/C++. Also to add encryption and unicode.
class TZip;
class RageFile;
typedef unsigned long ZRESULT;
// return codes from any of the zip functions. Listed later.
class CreateZip
{
TZip* hz;
public:
CreateZip();
bool Start(RageFile *f);
bool AddFile(RString fn);
bool AddDir(RString fn);
bool Finish();
RString GetError();
};
// e.g.
//
// (1) Traditional use, creating a zipfile from existing files
// HZIP hz = CreateZip("c:\\simple1.zip",0);
// ZipAdd(hz,"znsimple.bmp", "c:\\simple.bmp");
// ZipAdd(hz,"znsimple.txt", "c:\\simple.txt");
// CloseZip(hz);
//
// (2) Memory use, creating an auto-allocated mem-based zip file from various sources
// HZIP hz = CreateZip(0,100000, 0);
// // adding a conventional file...
// ZipAdd(hz,"src1.txt", "c:\\src1.txt");
// // adding something from memory...
// char buf[1000]; for (int i=0; i<1000; i++) buf[i]=(char)(i&0x7F);
// ZipAdd(hz,"file.dat", buf,1000);
// // adding something from a pipe...
// HANDLE hread,hwrite; CreatePipe(&hread,&hwrite,NULL,0);
// HANDLE hthread = CreateThread(0,0,ThreadFunc,(void*)hwrite,0,0);
// ZipAdd(hz,"unz3.dat", hread,1000); // the '1000' is optional.
// WaitForSingleObject(hthread,INFINITE);
// CloseHandle(hthread); CloseHandle(hread);
// ... meanwhile DWORD WINAPI ThreadFunc(void *dat)
// { HANDLE hwrite = (HANDLE)dat;
// char buf[1000]={17};
// DWORD writ; WriteFile(hwrite,buf,1000,&writ,NULL);
// CloseHandle(hwrite);
// return 0;
// }
// // and now that the zip is created, let's do something with it:
// void *zbuf; unsigned long zlen; ZipGetMemory(hz,&zbuf,&zlen);
// HANDLE hfz = CreateFile("test2.zip",GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
// DWORD writ; WriteFile(hfz,zbuf,zlen,&writ,NULL);
// CloseHandle(hfz);
// CloseZip(hz);
//
// (3) Handle use, for file handles and pipes
// HANDLE hzread,hzwrite; CreatePipe(&hzread,&hzwrite,0,0);
// HANDLE hthread = CreateThread(0,0,ZipReceiverThread,(void*)hzread,0,0);
// HZIP hz = CreateZipHandle(hzwrite,0);
// // ... add to it
// CloseZip(hz);
// CloseHandle(hzwrite);
// WaitForSingleObject(hthread,INFINITE);
// CloseHandle(hthread);
// ... meanwhile DWORD WINAPI ZipReceiverThread(void *dat)
// { HANDLE hread = (HANDLE)dat;
// char buf[1000];
// while (true)
// { DWORD red; ReadFile(hread,buf,1000,&red,NULL);
// // ... and do something with this zip data we're receiving
// if (red==0) break;
// }
// CloseHandle(hread);
// return 0;
// }
#endif
+1
View File
@@ -136,6 +136,7 @@ Course.cpp Course.h \
CourseLoaderCRS.cpp CourseLoaderCRS.h \
CourseUtil.cpp CourseUtil.h \
CourseWriterCRS.cpp CourseWriterCRS.h \
CreateZip.cpp CreateZip.h \
CryptHelpers.cpp CryptHelpers.h \
DateTime.cpp DateTime.h \
Difficulty.cpp Difficulty.h \
+40 -40
View File
@@ -1,40 +1,40 @@
/* NotesWriterJson - Writes a Song to a .json file. */
#ifndef NotesWriterJson_H
#define NotesWriterJson_H
class Song;
class Steps;
namespace NotesWriterJson
{
static bool WriteSong( const RString &sFile, const Song &out, bool bWriteSteps );
static bool WriteSteps( const RString &sFile, const Steps &out );
};
#endif
/*
* (c) 2001-2010 Chris Danford, Glenn Maynard
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* NotesWriterJson - Writes a Song to a .json file. */
#ifndef NotesWriterJson_H
#define NotesWriterJson_H
class Song;
class Steps;
namespace NotesWriterJson
{
bool WriteSong( const RString &sFile, const Song &out, bool bWriteSteps );
bool WriteSteps( const RString &sFile, const Steps &out );
};
#endif
/*
* (c) 2001-2010 Chris Danford, Glenn Maynard
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
+2346 -2343
View File
File diff suppressed because it is too large Load Diff
+95 -91
View File
@@ -1,91 +1,95 @@
#include "global.h"
#include "ScoreDisplayRave.h"
#include "RageUtil.h"
#include "RageLog.h"
#include "ThemeManager.h"
#include "ActorUtil.h"
#include "PlayerState.h"
ScoreDisplayRave::ScoreDisplayRave()
{
LOG->Trace( "ScoreDisplayRave::ScoreDisplayRave()" );
m_lastLevelSeen = ATTACK_LEVEL_1;
for( int i=0; i<NUM_ATTACK_LEVELS; i++ )
{
m_sprMeter[i].Load( THEME->GetPathG("ScoreDisplayRave",ssprintf("stream level%d",i+1)) );
m_sprMeter[i].SetCropRight( 1.f );
}
m_textLevel.LoadFromFont( THEME->GetPathF("ScoreDisplayRave","level") );
m_textLevel.SetText( "1" );
}
void ScoreDisplayRave::Init( const PlayerState* pPlayerState, const PlayerStageStats* pPlayerStageStats )
{
ScoreDisplay::Init( pPlayerState, pPlayerStageStats );
PlayerNumber pn = pPlayerState->m_PlayerNumber;
m_sprFrameBase.Load( THEME->GetPathG("ScoreDisplayRave",ssprintf("frame base p%d",pn+1)) );
this->AddChild( m_sprFrameBase );
for( int i=0; i<NUM_ATTACK_LEVELS; i++ )
{
m_sprMeter[i].SetName( ssprintf("MeterP%d",pn+1) );
LOAD_ALL_COMMANDS_AND_SET_XY( m_sprMeter[i] );
this->AddChild( &m_sprMeter[i] );
}
m_textLevel.SetName( ssprintf("LevelP%d",pn+1) );
LOAD_ALL_COMMANDS_AND_SET_XY( m_textLevel );
this->AddChild( &m_textLevel );
m_sprFrameOverlay.Load( THEME->GetPathG("ScoreDisplayRave",ssprintf("frame overlay p%d",pn+1)) );
this->AddChild( m_sprFrameOverlay );
}
void ScoreDisplayRave::Update( float fDelta )
{
ScoreDisplay::Update( fDelta );
float fLevel = m_pPlayerState->m_fSuperMeter;
AttackLevel level = (AttackLevel)(int)fLevel;
if( level != m_lastLevelSeen )
{
m_sprMeter[m_lastLevelSeen].SetCropRight( 1.f );
m_lastLevelSeen = level;
m_textLevel.SetText( ssprintf("%d",level+1) );
}
float fPercent = fLevel - level;
m_sprMeter[level].SetCropRight( 1-fPercent );
}
/*
* (c) 2003 Chris Danford
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "global.h"
#include "ScoreDisplayRave.h"
#include "RageUtil.h"
#include "RageLog.h"
#include "ThemeManager.h"
#include "ActorUtil.h"
#include "PlayerState.h"
ScoreDisplayRave::ScoreDisplayRave()
{
LOG->Trace( "ScoreDisplayRave::ScoreDisplayRave()" );
m_lastLevelSeen = ATTACK_LEVEL_1;
for( int i=0; i<NUM_ATTACK_LEVELS; i++ )
{
m_sprMeter[i].Load( THEME->GetPathG("ScoreDisplayRave",ssprintf("stream level%d",i+1)) );
m_sprMeter[i].SetCropRight( 1.f );
}
m_textLevel.LoadFromFont( THEME->GetPathF("ScoreDisplayRave","level") );
m_textLevel.SetText( "1" );
}
void ScoreDisplayRave::Init( const PlayerState* pPlayerState, const PlayerStageStats* pPlayerStageStats )
{
ScoreDisplay::Init( pPlayerState, pPlayerStageStats );
PlayerNumber pn = pPlayerState->m_PlayerNumber;
m_sprFrameBase.Load( THEME->GetPathG("ScoreDisplayRave",ssprintf("frame base p%d",pn+1)) );
m_sprFrameBase->SetName( ssprintf("FrameBaseP%d",pn+1) );
LOAD_ALL_COMMANDS_AND_SET_XY( m_sprFrameBase );
this->AddChild( m_sprFrameBase );
for( int i=0; i<NUM_ATTACK_LEVELS; i++ )
{
m_sprMeter[i].SetName( ssprintf("MeterP%d",pn+1) );
LOAD_ALL_COMMANDS_AND_SET_XY( m_sprMeter[i] );
this->AddChild( &m_sprMeter[i] );
}
m_textLevel.SetName( ssprintf("LevelP%d",pn+1) );
LOAD_ALL_COMMANDS_AND_SET_XY( m_textLevel );
this->AddChild( &m_textLevel );
m_sprFrameOverlay.Load( THEME->GetPathG("ScoreDisplayRave",ssprintf("frame overlay p%d",pn+1)) );
m_sprFrameOverlay->SetName( ssprintf("FrameOverP%d",pn+1) );
LOAD_ALL_COMMANDS_AND_SET_XY( m_sprFrameOverlay );
this->AddChild( m_sprFrameOverlay );
}
void ScoreDisplayRave::Update( float fDelta )
{
ScoreDisplay::Update( fDelta );
float fLevel = m_pPlayerState->m_fSuperMeter;
AttackLevel level = (AttackLevel)(int)fLevel;
if( level != m_lastLevelSeen )
{
m_sprMeter[m_lastLevelSeen].SetCropRight( 1.f );
m_lastLevelSeen = level;
m_textLevel.SetText( ssprintf("%d",level+1) );
}
float fPercent = fLevel - level;
m_sprMeter[level].SetCropRight( 1-fPercent );
}
/*
* (c) 2003 Chris Danford
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
+2955 -2944
View File
File diff suppressed because it is too large Load Diff
+356 -353
View File
@@ -1,353 +1,356 @@
#include "global.h"
#include "ScreenHowToPlay.h"
#include "ThemeManager.h"
#include "GameState.h"
#include "Steps.h"
#include "GameManager.h"
#include "NotesLoaderSM.h"
#include "NotesLoaderSSC.h"
#include "GameSoundManager.h"
#include "Model.h"
#include "ThemeMetric.h"
#include "PlayerState.h"
#include "Style.h"
#include "PrefsManager.h"
#include "CharacterManager.h"
#include "StatsManager.h"
#include "RageDisplay.h"
#include "SongUtil.h"
#include "Character.h"
#include "LifeMeterBar.h"
static const ThemeMetric<int> NUM_W2S ("ScreenHowToPlay","NumW2s");
static const ThemeMetric<int> NUM_MISSES ("ScreenHowToPlay","NumMisses");
static const ThemeMetric<bool> USE_CHARACTER ("ScreenHowToPlay","UseCharacter");
static const ThemeMetric<bool> USE_PAD ("ScreenHowToPlay","UsePad");
static const ThemeMetric<bool> USE_PLAYER ("ScreenHowToPlay","UsePlayer");
static const ThemeMetric<RString> CHARACTER_NAME("ScreenHowToPlay","CharacterName");
enum Animation
{
ANIM_DANCE_PAD,
ANIM_DANCE_PADS,
ANIM_UP,
ANIM_DOWN,
ANIM_LEFT,
ANIM_RIGHT,
ANIM_JUMPLR,
NUM_ANIMATIONS
};
static const RString anims[NUM_ANIMATIONS] =
{
"DancePad.txt",
"DancePads.txt",
"BeginnerHelper_step-up.bones.txt",
"BeginnerHelper_step-down.bones.txt",
"BeginnerHelper_step-left.bones.txt",
"BeginnerHelper_step-right.bones.txt",
"BeginnerHelper_step-jumplr.bones.txt"
};
static RString GetAnimPath( Animation a )
{
return RString("Characters/") + anims[a];
}
static bool HaveAllCharAnimations()
{
for( int i = ANIM_UP; i < NUM_ANIMATIONS; ++i )
if( !DoesFileExist( GetAnimPath( (Animation) i ) ) )
return false;
return true;
}
REGISTER_SCREEN_CLASS( ScreenHowToPlay );
ScreenHowToPlay::ScreenHowToPlay()
{
m_iW2s = 0;
m_iNumW2s = NUM_W2S;
// initialize these because they might not be used.
m_pLifeMeterBar = NULL;
m_pmCharacter = NULL;
m_pmDancePad = NULL;
}
void ScreenHowToPlay::Init()
{
ScreenAttract::Init();
if( (bool)USE_PAD && DoesFileExist( GetAnimPath(ANIM_DANCE_PAD) ) )
{
m_pmDancePad = new Model;
m_pmDancePad->SetName( "Pad" );
m_pmDancePad->LoadMilkshapeAscii( GetAnimPath(ANIM_DANCE_PAD) );
// xxx: hardcoded rotation. can be undone, but still. -freem
m_pmDancePad->SetRotationX( 35 );
ActorUtil::LoadAllCommandsAndSetXY( m_pmDancePad, m_sName );
}
// Display a character
vector<Character*> vpCharacters;
CHARMAN->GetCharacters( vpCharacters );
if( (bool)USE_CHARACTER && vpCharacters.size() && HaveAllCharAnimations() )
{
Character* displayChar;
if( !CHARACTER_NAME.GetValue().empty() && CHARMAN->GetCharacterFromID(CHARACTER_NAME) )
displayChar = CHARMAN->GetCharacterFromID(CHARACTER_NAME);
else
displayChar = CHARMAN->GetRandomCharacter();
RString sModelPath = displayChar->GetModelPath();
if( sModelPath != "" )
{
m_pmCharacter = new Model;
m_pmCharacter->SetName( "Character" );
m_pmCharacter->LoadMilkshapeAscii( displayChar->GetModelPath() );
m_pmCharacter->LoadMilkshapeAsciiBones( "Step-LEFT", GetAnimPath( ANIM_LEFT ) );
m_pmCharacter->LoadMilkshapeAsciiBones( "Step-DOWN", GetAnimPath( ANIM_DOWN ) );
m_pmCharacter->LoadMilkshapeAsciiBones( "Step-UP", GetAnimPath( ANIM_UP ) );
m_pmCharacter->LoadMilkshapeAsciiBones( "Step-RIGHT", GetAnimPath( ANIM_RIGHT ) );
m_pmCharacter->LoadMilkshapeAsciiBones( "Step-JUMPLR", GetAnimPath( ANIM_JUMPLR ) );
RString sRestFile = displayChar->GetRestAnimationPath();
ASSERT( !sRestFile.empty() );
m_pmCharacter->LoadMilkshapeAsciiBones( "rest",displayChar->GetRestAnimationPath() );
m_pmCharacter->SetDefaultAnimation( "rest" );
m_pmCharacter->PlayAnimation( "rest" ); // Stay bouncing after a step has finished animating.
// xxx: hardcoded rotation. can be undone, but still. -freem
m_pmCharacter->SetRotationX( 40 );
m_pmCharacter->SetCullMode( CULL_NONE ); // many of the models floating around have the vertex order flipped
ActorUtil::LoadAllCommandsAndSetXY( m_pmCharacter, m_sName );
}
}
GAMESTATE->SetCurrentStyle( GAMEMAN->GetHowToPlayStyleForGame(GAMESTATE->m_pCurGame) );
if( USE_PLAYER )
{
m_pLifeMeterBar = new LifeMeterBar;
m_pLifeMeterBar->SetName("LifeMeterBar");
m_pLifeMeterBar->Load( GAMESTATE->m_pPlayerState[PLAYER_1], &STATSMAN->m_CurStageStats.m_player[PLAYER_1] );
ActorUtil::LoadAllCommandsAndSetXY( m_pLifeMeterBar, m_sName );
m_pLifeMeterBar->FillForHowToPlay( NUM_W2S, NUM_MISSES );
// Allow themers to use either a .ssc or .sm file for this. -aj
RString sStepsPath = THEME->GetPathO(m_sName, "steps");
SSCLoader loaderSSC;
SMLoader loaderSM;
if( sStepsPath.Right(4) == ".ssc" )
loaderSSC.LoadFromSimfile( sStepsPath, m_Song, false );
else
loaderSM.LoadFromSimfile( sStepsPath, m_Song, false );
m_Song.AddAutoGenNotes();
const Style* pStyle = GAMESTATE->GetCurrentStyle();
Steps *pSteps = SongUtil::GetClosestNotes( &m_Song, pStyle->m_StepsType, Difficulty_Beginner );
ASSERT_M( pSteps != NULL, ssprintf("No playable steps of StepsType '%s' for ScreenHowToPlay", StringConversion::ToString(pStyle->m_StepsType).c_str()) );
pSteps->m_Timing.TidyUpData();
NoteData tempNoteData;
pSteps->GetNoteData( tempNoteData );
pStyle->GetTransformedNoteDataForStyle( PLAYER_1, tempNoteData, m_NoteData );
GAMESTATE->m_pCurSong.Set( &m_Song );
GAMESTATE->m_pCurSteps[PLAYER_1].Set(pSteps);
GAMESTATE->m_bGameplayLeadIn.Set( false );
GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerController = PC_AUTOPLAY;
m_Player->Init(
"Player",
GAMESTATE->m_pPlayerState[PLAYER_1],
NULL,
m_pLifeMeterBar,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL );
m_Player.Load( m_NoteData );
m_Player->SetName( "Player" );
this->AddChild( m_Player );
ActorUtil::LoadAllCommandsAndSetXY( m_Player, m_sName );
// Don't show judgment
PO_GROUP_ASSIGN( GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions, ModsLevel_Stage, m_fBlind, 1.0f );
GAMESTATE->SetMasterPlayerNumber(PLAYER_1);
GAMESTATE->m_bDemonstrationOrJukebox = true;
}
// deferred until after the player, so the notes go under it
if( m_pLifeMeterBar )
this->AddChild( m_pLifeMeterBar );
if( m_pmDancePad )
this->AddChild( m_pmDancePad );
if( m_pmCharacter )
this->AddChild( m_pmCharacter );
m_fFakeSecondsIntoSong = 0;
this->MoveToTail( &m_In );
this->MoveToTail( &m_Out );
}
ScreenHowToPlay::~ScreenHowToPlay()
{
delete m_pLifeMeterBar;
delete m_pmCharacter;
delete m_pmDancePad;
}
void ScreenHowToPlay::Step()
{
// xxx: assumes dance. -freem
#define ST_LEFT 0x01
#define ST_DOWN 0x02
#define ST_UP 0x04
#define ST_RIGHT 0x08
#define ST_JUMPLR (ST_LEFT | ST_RIGHT)
#define ST_JUMPUD (ST_UP | ST_DOWN)
int iStep = 0;
const int iNoteRow = BeatToNoteRowNotRounded( GAMESTATE->m_Position.m_fSongBeat + 0.6f );
// if we want to miss from here on out, don't process steps.
if( m_iW2s < m_iNumW2s && m_NoteData.IsThereATapAtRow( iNoteRow ) )
{
const int iNumTracks = m_NoteData.GetNumTracks();
for( int k=0; k<iNumTracks; k++ )
if( m_NoteData.GetTapNote(k, iNoteRow).type == TapNote::tap )
iStep |= 1 << k;
switch( iStep )
{
case ST_LEFT: m_pmCharacter->PlayAnimation( "Step-LEFT", 1.8f ); break;
case ST_RIGHT: m_pmCharacter->PlayAnimation( "Step-RIGHT", 1.8f ); break;
case ST_UP: m_pmCharacter->PlayAnimation( "Step-UP", 1.8f ); break;
case ST_DOWN: m_pmCharacter->PlayAnimation( "Step-DOWN", 1.8f ); break;
case ST_JUMPLR: m_pmCharacter->PlayAnimation( "Step-JUMPLR", 1.8f ); break;
case ST_JUMPUD:
// Until I can get an UP+DOWN jump animation, this will have to do.
m_pmCharacter->PlayAnimation( "Step-JUMPLR", 1.8f );
m_pmCharacter->StopTweening();
m_pmCharacter->BeginTweening( GAMESTATE->m_Position.m_fCurBPS /8, TWEEN_LINEAR );
m_pmCharacter->SetRotationY( 90 );
m_pmCharacter->BeginTweening( (1/(GAMESTATE->m_Position.m_fCurBPS * 2) ) ); //sleep between jump-frames
m_pmCharacter->BeginTweening( GAMESTATE->m_Position.m_fCurBPS /6, TWEEN_LINEAR );
m_pmCharacter->SetRotationY( 0 );
break;
}
}
}
void ScreenHowToPlay::Update( float fDelta )
{
if( GAMESTATE->m_pCurSong != NULL )
{
GAMESTATE->UpdateSongPosition( m_fFakeSecondsIntoSong, GAMESTATE->m_pCurSong->m_SongTiming );
m_fFakeSecondsIntoSong += fDelta;
static int iLastNoteRowCounted = 0;
int iCurNoteRow = BeatToNoteRowNotRounded( GAMESTATE->m_Position.m_fSongBeat );
if( iCurNoteRow != iLastNoteRowCounted &&m_NoteData.IsThereATapAtRow(iCurNoteRow) )
{
if( m_pLifeMeterBar && !m_Player )
{
if ( m_iW2s < m_iNumW2s )
m_pLifeMeterBar->ChangeLife( TNS_W2 );
else
m_pLifeMeterBar->ChangeLife( TNS_Miss );
}
m_iW2s++;
iLastNoteRowCounted = iCurNoteRow;
}
// Once we hit the number of perfects we want, we want to fail. Switch
// the controller to HUMAN. Since we aren't taking input, the steps will
// always be misses.
if( m_iW2s > m_iNumW2s )
GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerController = PC_HUMAN;
// Per the above code, we don't always want the character stepping.
// If they try to make all of the steps in the miss part, they look
// silly. Have then stand still instead. - freem
if ( m_pmCharacter )
{
if( m_iW2s <= m_iNumW2s )
Step();
}
}
ScreenAttract::Update( fDelta );
}
void ScreenHowToPlay::HandleScreenMessage( const ScreenMessage SM )
{
if( SM == SM_GainFocus )
{
// We do this ourself.
SOUND->HandleSongTimer( false );
}
else if( SM == SM_LoseFocus )
{
SOUND->HandleSongTimer( true );
}
else if( SM == SM_GoToNextScreen )
{
GAMESTATE->Reset();
}
ScreenAttract::HandleScreenMessage( SM );
}
// lua start
#include "LuaBinding.h"
/** @brief Allow Lua to have access to the ScreenHowToPlay. */
class LunaScreenHowToPlay: public Luna<ScreenHowToPlay>
{
public:
static int GetLifeMeter( T* p, lua_State *L )
{
//PlayerNumber pn = Enum::Check<PlayerNumber>( L, 1 );
p->m_pLifeMeterBar->PushSelf( L );
return 1;
}
LunaScreenHowToPlay()
{
ADD_METHOD( GetLifeMeter );
}
};
LUA_REGISTER_DERIVED_CLASS( ScreenHowToPlay, ScreenAttract )
// lua end
/*
* (c) 2001-2004 Chris Danford, Thad Ward
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "global.h"
#include "ScreenHowToPlay.h"
#include "ThemeManager.h"
#include "GameState.h"
#include "Steps.h"
#include "GameManager.h"
#include "NotesLoaderSM.h"
#include "NotesLoaderSSC.h"
#include "GameSoundManager.h"
#include "Model.h"
#include "ThemeMetric.h"
#include "PlayerState.h"
#include "Style.h"
#include "PrefsManager.h"
#include "CharacterManager.h"
#include "StatsManager.h"
#include "RageDisplay.h"
#include "SongUtil.h"
#include "Character.h"
#include "LifeMeterBar.h"
static const ThemeMetric<int> NUM_W2S ("ScreenHowToPlay","NumW2s");
static const ThemeMetric<int> NUM_MISSES ("ScreenHowToPlay","NumMisses");
static const ThemeMetric<bool> USE_CHARACTER ("ScreenHowToPlay","UseCharacter");
static const ThemeMetric<bool> USE_PAD ("ScreenHowToPlay","UsePad");
static const ThemeMetric<bool> USE_PLAYER ("ScreenHowToPlay","UsePlayer");
static const ThemeMetric<RString> CHARACTER_NAME("ScreenHowToPlay","CharacterName");
enum Animation
{
ANIM_DANCE_PAD,
ANIM_DANCE_PADS,
ANIM_UP,
ANIM_DOWN,
ANIM_LEFT,
ANIM_RIGHT,
ANIM_JUMPLR,
NUM_ANIMATIONS
};
static const RString anims[NUM_ANIMATIONS] =
{
"DancePad.txt",
"DancePads.txt",
"BeginnerHelper_step-up.bones.txt",
"BeginnerHelper_step-down.bones.txt",
"BeginnerHelper_step-left.bones.txt",
"BeginnerHelper_step-right.bones.txt",
"BeginnerHelper_step-jumplr.bones.txt"
};
static RString GetAnimPath( Animation a )
{
return RString("Characters/") + anims[a];
}
static bool HaveAllCharAnimations()
{
for( int i = ANIM_UP; i < NUM_ANIMATIONS; ++i )
if( !DoesFileExist( GetAnimPath( (Animation) i ) ) )
return false;
return true;
}
REGISTER_SCREEN_CLASS( ScreenHowToPlay );
ScreenHowToPlay::ScreenHowToPlay()
{
m_iW2s = 0;
m_iNumW2s = NUM_W2S;
// initialize these because they might not be used.
m_pLifeMeterBar = NULL;
m_pmCharacter = NULL;
m_pmDancePad = NULL;
}
void ScreenHowToPlay::Init()
{
ScreenAttract::Init();
if( (bool)USE_PAD && DoesFileExist( GetAnimPath(ANIM_DANCE_PAD) ) )
{
m_pmDancePad = new Model;
m_pmDancePad->SetName( "Pad" );
m_pmDancePad->LoadMilkshapeAscii( GetAnimPath(ANIM_DANCE_PAD) );
// xxx: hardcoded rotation. can be undone, but still. -freem
m_pmDancePad->SetRotationX( 35 );
ActorUtil::LoadAllCommandsAndSetXY( m_pmDancePad, m_sName );
}
// Display a character
vector<Character*> vpCharacters;
CHARMAN->GetCharacters( vpCharacters );
if( (bool)USE_CHARACTER && vpCharacters.size() && HaveAllCharAnimations() )
{
Character* displayChar;
if( !CHARACTER_NAME.GetValue().empty() && CHARMAN->GetCharacterFromID(CHARACTER_NAME) )
displayChar = CHARMAN->GetCharacterFromID(CHARACTER_NAME);
else
displayChar = CHARMAN->GetRandomCharacter();
RString sModelPath = displayChar->GetModelPath();
if( sModelPath != "" )
{
m_pmCharacter = new Model;
m_pmCharacter->SetName( "Character" );
m_pmCharacter->LoadMilkshapeAscii( displayChar->GetModelPath() );
m_pmCharacter->LoadMilkshapeAsciiBones( "Step-LEFT", GetAnimPath( ANIM_LEFT ) );
m_pmCharacter->LoadMilkshapeAsciiBones( "Step-DOWN", GetAnimPath( ANIM_DOWN ) );
m_pmCharacter->LoadMilkshapeAsciiBones( "Step-UP", GetAnimPath( ANIM_UP ) );
m_pmCharacter->LoadMilkshapeAsciiBones( "Step-RIGHT", GetAnimPath( ANIM_RIGHT ) );
m_pmCharacter->LoadMilkshapeAsciiBones( "Step-JUMPLR", GetAnimPath( ANIM_JUMPLR ) );
RString sRestFile = displayChar->GetRestAnimationPath();
ASSERT( !sRestFile.empty() );
m_pmCharacter->LoadMilkshapeAsciiBones( "rest",displayChar->GetRestAnimationPath() );
m_pmCharacter->SetDefaultAnimation( "rest" );
m_pmCharacter->PlayAnimation( "rest" ); // Stay bouncing after a step has finished animating.
// xxx: hardcoded rotation. can be undone, but still. -freem
m_pmCharacter->SetRotationX( 40 );
m_pmCharacter->SetCullMode( CULL_NONE ); // many of the models floating around have the vertex order flipped
m_pmCharacter->RunCommands( displayChar->m_cmdInit ); // run InitCommand from file
ActorUtil::LoadAllCommandsAndSetXY( m_pmCharacter, m_sName );
}
}
GAMESTATE->SetCurrentStyle( GAMEMAN->GetHowToPlayStyleForGame(GAMESTATE->m_pCurGame) );
if( USE_PLAYER )
{
GAMESTATE->SetMasterPlayerNumber(PLAYER_1);
m_pLifeMeterBar = new LifeMeterBar;
m_pLifeMeterBar->Load( GAMESTATE->m_pPlayerState[PLAYER_1], &STATSMAN->m_CurStageStats.m_player[PLAYER_1] );
m_pLifeMeterBar->SetName("LifeMeterBar");
ActorUtil::LoadAllCommandsAndSetXY( m_pLifeMeterBar, m_sName );
m_pLifeMeterBar->FillForHowToPlay( NUM_W2S, NUM_MISSES );
// Allow themers to use either a .ssc or .sm file for this. -aj
RString sStepsPath = THEME->GetPathO(m_sName, "steps");
SSCLoader loaderSSC;
SMLoader loaderSM;
if( sStepsPath.Right(4) == ".ssc" )
loaderSSC.LoadFromSimfile( sStepsPath, m_Song, false );
else
loaderSM.LoadFromSimfile( sStepsPath, m_Song, false );
m_Song.AddAutoGenNotes();
const Style* pStyle = GAMESTATE->GetCurrentStyle();
Steps *pSteps = SongUtil::GetClosestNotes( &m_Song, pStyle->m_StepsType, Difficulty_Beginner );
ASSERT_M( pSteps != NULL, ssprintf("No playable steps of StepsType '%s' for ScreenHowToPlay", StringConversion::ToString(pStyle->m_StepsType).c_str()) );
pSteps->m_Timing.TidyUpData();
NoteData tempNoteData;
pSteps->GetNoteData( tempNoteData );
pStyle->GetTransformedNoteDataForStyle( PLAYER_1, tempNoteData, m_NoteData );
GAMESTATE->m_pCurSong.Set( &m_Song );
GAMESTATE->m_pCurSteps[PLAYER_1].Set(pSteps);
GAMESTATE->m_bGameplayLeadIn.Set( false );
GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerController = PC_AUTOPLAY;
m_Player->Init(
"Player",
GAMESTATE->m_pPlayerState[PLAYER_1],
NULL,
m_pLifeMeterBar,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL );
m_Player.Load( m_NoteData );
m_Player->SetName( "Player" );
this->AddChild( m_Player );
ActorUtil::LoadAllCommandsAndSetXY( m_Player, m_sName );
// Don't show judgment
PO_GROUP_ASSIGN( GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions, ModsLevel_Stage, m_fBlind, 1.0f );
GAMESTATE->m_bDemonstrationOrJukebox = true;
}
// deferred until after the player, so the notes go under it
if( m_pLifeMeterBar )
this->AddChild( m_pLifeMeterBar );
if( m_pmDancePad )
this->AddChild( m_pmDancePad );
if( m_pmCharacter )
this->AddChild( m_pmCharacter );
m_fFakeSecondsIntoSong = 0;
this->MoveToTail( &m_In );
this->MoveToTail( &m_Out );
}
ScreenHowToPlay::~ScreenHowToPlay()
{
delete m_pLifeMeterBar;
delete m_pmCharacter;
delete m_pmDancePad;
}
void ScreenHowToPlay::Step()
{
// xxx: assumes dance. -freem
#define ST_LEFT 0x01
#define ST_DOWN 0x02
#define ST_UP 0x04
#define ST_RIGHT 0x08
#define ST_JUMPLR (ST_LEFT | ST_RIGHT)
#define ST_JUMPUD (ST_UP | ST_DOWN)
int iStep = 0;
const int iNoteRow = BeatToNoteRowNotRounded( GAMESTATE->m_Position.m_fSongBeat + 0.6f );
// if we want to miss from here on out, don't process steps.
if( m_iW2s < m_iNumW2s && m_NoteData.IsThereATapAtRow( iNoteRow ) )
{
const int iNumTracks = m_NoteData.GetNumTracks();
for( int k=0; k<iNumTracks; k++ )
if( m_NoteData.GetTapNote(k, iNoteRow).type == TapNote::tap )
iStep |= 1 << k;
switch( iStep )
{
case ST_LEFT: m_pmCharacter->PlayAnimation( "Step-LEFT", 1.8f ); break;
case ST_RIGHT: m_pmCharacter->PlayAnimation( "Step-RIGHT", 1.8f ); break;
case ST_UP: m_pmCharacter->PlayAnimation( "Step-UP", 1.8f ); break;
case ST_DOWN: m_pmCharacter->PlayAnimation( "Step-DOWN", 1.8f ); break;
case ST_JUMPLR: m_pmCharacter->PlayAnimation( "Step-JUMPLR", 1.8f ); break;
case ST_JUMPUD:
// Until I can get an UP+DOWN jump animation, this will have to do.
m_pmCharacter->PlayAnimation( "Step-JUMPLR", 1.8f );
m_pmCharacter->StopTweening();
m_pmCharacter->BeginTweening( GAMESTATE->m_Position.m_fCurBPS /8, TWEEN_LINEAR );
m_pmCharacter->SetRotationY( 90 );
m_pmCharacter->BeginTweening( (1/(GAMESTATE->m_Position.m_fCurBPS * 2) ) ); //sleep between jump-frames
m_pmCharacter->BeginTweening( GAMESTATE->m_Position.m_fCurBPS /6, TWEEN_LINEAR );
m_pmCharacter->SetRotationY( 0 );
break;
}
}
}
void ScreenHowToPlay::Update( float fDelta )
{
if( GAMESTATE->m_pCurSong != NULL )
{
RageTimer tm;
GAMESTATE->UpdateSongPosition( m_fFakeSecondsIntoSong, GAMESTATE->m_pCurSong->m_SongTiming, tm, true );
m_fFakeSecondsIntoSong += fDelta;
static int iLastNoteRowCounted = 0;
int iCurNoteRow = BeatToNoteRowNotRounded( GAMESTATE->m_Position.m_fSongBeat );
if( iCurNoteRow != iLastNoteRowCounted &&m_NoteData.IsThereATapAtRow(iCurNoteRow) )
{
if( m_pLifeMeterBar && !m_Player )
{
if ( m_iW2s < m_iNumW2s )
m_pLifeMeterBar->ChangeLife( TNS_W2 );
else
m_pLifeMeterBar->ChangeLife( TNS_Miss );
}
m_iW2s++;
iLastNoteRowCounted = iCurNoteRow;
}
// Once we hit the number of perfects we want, we want to fail. Switch
// the controller to HUMAN. Since we aren't taking input, the steps will
// always be misses.
if( m_iW2s > m_iNumW2s )
GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerController = PC_HUMAN;
// Per the above code, we don't always want the character stepping.
// If they try to make all of the steps in the miss part, they look
// silly. Have then stand still instead. - freem
if ( m_pmCharacter )
{
if( m_iW2s <= m_iNumW2s )
Step();
}
}
ScreenAttract::Update( fDelta );
}
void ScreenHowToPlay::HandleScreenMessage( const ScreenMessage SM )
{
if( SM == SM_GainFocus )
{
// We do this ourself.
SOUND->HandleSongTimer( false );
}
else if( SM == SM_LoseFocus )
{
SOUND->HandleSongTimer( true );
}
else if( SM == SM_GoToNextScreen )
{
GAMESTATE->Reset();
}
ScreenAttract::HandleScreenMessage( SM );
}
// lua start
#include "LuaBinding.h"
/** @brief Allow Lua to have access to the ScreenHowToPlay. */
class LunaScreenHowToPlay: public Luna<ScreenHowToPlay>
{
public:
static int GetLifeMeter( T* p, lua_State *L )
{
//PlayerNumber pn = Enum::Check<PlayerNumber>( L, 1 );
p->m_pLifeMeterBar->PushSelf( L );
return 1;
}
LunaScreenHowToPlay()
{
ADD_METHOD( GetLifeMeter );
}
};
LUA_REGISTER_DERIVED_CLASS( ScreenHowToPlay, ScreenAttract )
// lua end
/*
* (c) 2001-2004 Chris Danford, Thad Ward
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
+363 -362
View File
@@ -1,362 +1,363 @@
#include "global.h"
#include "ScreenRanking.h"
#include "ScreenManager.h"
#include "SongManager.h"
#include "GameState.h"
#include "GameManager.h"
#include "ProfileManager.h"
#include "Profile.h"
static const char *RankingTypeNames[] = {
"Category",
"Course",
};
XToString( RankingType );
LuaXType( RankingType );
AutoScreenMessage( SM_ShowNextPage );
AutoScreenMessage( SM_HidePage );
REGISTER_SCREEN_CLASS( ScreenRanking );
#define BULLET_X(row) (BULLET_START_X+ROW_SPACING_X*row)
#define BULLET_Y(row) (BULLET_START_Y+ROW_SPACING_Y*row)
#define NAME_X(row) (NAME_START_X+ROW_SPACING_X*row)
#define NAME_Y(row) (NAME_START_Y+ROW_SPACING_Y*row)
#define SCORE_X(row) (SCORE_START_X+ROW_SPACING_X*row)
#define SCORE_Y(row) (SCORE_START_Y+ROW_SPACING_Y*row)
#define POINTS_X(row) (POINTS_START_X+ROW_SPACING_X*row)
#define POINTS_Y(row) (POINTS_START_Y+ROW_SPACING_Y*row)
#define TIME_X(row) (TIME_START_X+ROW_SPACING_X*row)
#define TIME_Y(row) (TIME_START_Y+ROW_SPACING_Y*row)
static RString STEPS_TYPE_COLOR_NAME( size_t i ) { return ssprintf("StepsTypeColor%d",int(i+1)); }
void ScreenRanking::Init()
{
STEPS_TYPES_TO_SHOW.Load( m_sName,"StepsTypesToHide" ); // tricky: The metric name is "hide" because ThemeMetricStepsTypesToShow takes a list of what to hide and returns what StepsTypes to show
PAGE_FADE_SECONDS.Load ( m_sName,"PageFadeSeconds" );
ScreenAttract::Init();
m_textStepsType.SetName( "StepsType" );
m_textStepsType.LoadFromFont( THEME->GetPathF(m_sName,"StepsType") );
m_textStepsType.SetShadowLength( 0 );
this->AddChild( &m_textStepsType );
LOAD_ALL_COMMANDS( m_textStepsType );
RANKING_TYPE.Load ( m_sName,"RankingType");
COURSES_TO_SHOW.Load ( m_sName,"CoursesToShow");
SECONDS_PER_PAGE.Load ( m_sName,"SecondsPerPage" );
NO_SCORE_NAME.Load( m_sName,"NoScoreName" );
ROW_SPACING_X.Load( m_sName,"RowSpacingX" );
ROW_SPACING_Y.Load( m_sName,"RowSpacingY" );
BULLET_START_X.Load( m_sName, "BulletStartX" );
BULLET_START_Y.Load( m_sName, "BulletStartY" );
NAME_START_X.Load( m_sName, "NameStartX" );
NAME_START_Y.Load( m_sName, "NameStartY" );
SCORE_START_X.Load( m_sName, "ScoreStartX" );
SCORE_START_Y.Load( m_sName, "ScoreStartY" );
POINTS_START_X.Load( m_sName, "PointsStartX" );
POINTS_START_Y.Load( m_sName, "PointsStartY" );
TIME_START_X.Load( m_sName, "TimeStartX" );
TIME_START_Y.Load( m_sName, "TimeStartY" );
STEPS_TYPE_COLOR.Load( m_sName,STEPS_TYPE_COLOR_NAME,NUM_RANKING_LINES );
if( RANKING_TYPE == RankingType_Category )
{
m_textCategory.SetName( "Category" );
m_textCategory.LoadFromFont( THEME->GetPathF(m_sName,"category") );
//m_textCategory.SetShadowLength( 0 );
this->AddChild( &m_textCategory );
LOAD_ALL_COMMANDS( m_textCategory );
for( unsigned i=0; i<STEPS_TYPES_TO_SHOW.GetValue().size(); i++ )
{
for( int c=0; c<NUM_RankingCategory; c++ )
{
PageToShow pts;
pts.colorIndex = i;
pts.category = (RankingCategory)c;
StepsType st = STEPS_TYPES_TO_SHOW.GetValue()[i];
pts.aTypes.push_back( make_pair(Difficulty_Invalid, st) );
m_vPagesToShow.push_back( pts );
}
}
}
if( RANKING_TYPE == RankingType_SpecificTrail )
{
m_Banner.SetName( "Banner" );
this->AddChild( &m_Banner );
LOAD_ALL_COMMANDS( m_Banner );
m_textCourseTitle.SetName( "CourseTitle" );
m_textCourseTitle.LoadFromFont( THEME->GetPathF(m_sName,"course title") );
//m_textCourseTitle.SetShadowLength( 0 );
this->AddChild( &m_textCourseTitle );
LOAD_ALL_COMMANDS( m_textCourseTitle );
vector<RString> asCoursePaths;
split( COURSES_TO_SHOW, ",", asCoursePaths, true );
for( unsigned i=0; i<STEPS_TYPES_TO_SHOW.GetValue().size(); i++ )
{
for( unsigned c=0; c<asCoursePaths.size(); c++ )
{
PageToShow pts;
pts.colorIndex = i;
StepsType st = STEPS_TYPES_TO_SHOW.GetValue()[i];
pts.aTypes.push_back( make_pair(Difficulty_Invalid, st) );
pts.pCourse = SONGMAN->GetCourseFromPath( asCoursePaths[c] );
if( pts.pCourse == NULL )
continue;
pts.pTrail = pts.pCourse->GetTrail( st );
if( pts.pTrail == NULL )
continue;
m_vPagesToShow.push_back( pts );
}
}
}
for( int l=0; l<NUM_RANKING_LINES; l++ )
{
m_sprBullets[l].Load( THEME->GetPathG( m_sName, ssprintf("bullets 1x%d",NUM_RANKING_LINES) ) );
m_sprBullets[l]->SetName( ssprintf("Bullet%d",l+1) );
m_sprBullets[l]->StopAnimating();
m_sprBullets[l]->SetState( l );
m_sprBullets[l]->SetXY( BULLET_X(l), BULLET_Y(l) );
ActorUtil::LoadAllCommands( *m_sprBullets[l], m_sName );
this->AddChild( m_sprBullets[l] );
m_textNames[l].SetName( ssprintf("Name%d",l+1) );
m_textNames[l].LoadFromFont( THEME->GetPathF(m_sName,"name") );
m_textNames[l].SetXY( NAME_X(l), NAME_Y(l) );
ActorUtil::LoadAllCommands( m_textNames[l], m_sName );
this->AddChild( &m_textNames[l] );
m_textScores[l].SetName( ssprintf("Score%d",l+1) );
m_textScores[l].LoadFromFont( THEME->GetPathF(m_sName,"score") );
m_textScores[l].SetXY( SCORE_X(l), SCORE_Y(l) );
ActorUtil::LoadAllCommands( m_textScores[l], m_sName );
this->AddChild( &m_textScores[l] );
m_textPoints[l].SetName( ssprintf("Points%d",l+1) );
m_textPoints[l].LoadFromFont( THEME->GetPathF(m_sName,"points") );
m_textPoints[l].SetVisible( false );
m_textPoints[l].SetXY( POINTS_X(l), POINTS_Y(l) );
ActorUtil::LoadAllCommands( m_textPoints[l], m_sName );
this->AddChild( &m_textPoints[l] );
m_textTime[l].SetName( ssprintf("Time%d",l+1) );
m_textTime[l].LoadFromFont( THEME->GetPathF(m_sName,"time") );
m_textTime[l].SetVisible( false );
m_textTime[l].SetXY( TIME_X(l), TIME_Y(l) );
ActorUtil::LoadAllCommands( m_textTime[l], m_sName );
this->AddChild( &m_textTime[l] );
}
}
void ScreenRanking::BeginScreen()
{
m_iNextPageToShow = 0;
ScreenAttract::BeginScreen();
this->HandleScreenMessage( SM_ShowNextPage );
}
void ScreenRanking::HandleScreenMessage( const ScreenMessage SM )
{
if( SM == SM_ShowNextPage )
{
if( m_iNextPageToShow < m_vPagesToShow.size() )
{
float fSecsToShow = SetPage( m_vPagesToShow[m_iNextPageToShow] );
++m_iNextPageToShow;
this->SortByDrawOrder();
this->PostScreenMessage( SM_HidePage, fSecsToShow-PAGE_FADE_SECONDS );
}
else
{
StartTransitioningScreen(SM_GoToNextScreen);
}
}
else if( SM == SM_HidePage )
{
this->PlayCommand( "SwitchPage" );
this->PostScreenMessage( SM_ShowNextPage, PAGE_FADE_SECONDS );
}
ScreenAttract::HandleScreenMessage( SM );
}
float ScreenRanking::SetPage( const PageToShow &pts )
{
// This is going to take a while to load. Possibly longer than one frame.
// So, zero the next update so we don't skip.
SCREENMAN->ZeroNextUpdate();
// init page
StepsType st = pts.aTypes.front().second;
m_textStepsType.SetText( GAMEMAN->GetStepsTypeInfo(st).GetLocalizedString() );
bool bShowScores = false;
bool bShowPoints = false;
bool bShowTime = false;
switch( RANKING_TYPE )
{
case RankingType_Category:
bShowScores = true;
break;
case RankingType_SpecificTrail:
bShowScores = !pts.pCourse->IsOni();
bShowPoints = pts.pCourse->IsOni();
bShowTime = pts.pCourse->IsOni();
break;
default: break;
}
for( int l=0; l<NUM_RANKING_LINES; l++ )
{
m_textNames[l].SetDiffuse( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
m_textScores[l].SetVisible( bShowScores );
m_textScores[l].SetDiffuse( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
m_textPoints[l].SetVisible( bShowPoints );
m_textPoints[l].SetDiffuse( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
m_textTime[l].SetVisible( bShowTime );
m_textTime[l].SetDiffuse( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
}
switch( RANKING_TYPE )
{
case RankingType_Category:
{
m_textCategory.SetText( ssprintf("Type %c", 'A'+pts.category) );
for( int l=0; l<NUM_RANKING_LINES; l++ )
{
// No need to shadow at this point.
st = pts.aTypes.front().second;
HighScoreList &hsl = PROFILEMAN->GetMachineProfile()->GetCategoryHighScoreList(st, pts.category);
HighScore hs;
bool bRecentHighScore = false;
if( l < (int)hsl.vHighScores.size() )
{
hs = hsl.vHighScores[l];
RString *psName = hsl.vHighScores[l].GetNameMutable();
bRecentHighScore = find( GAMESTATE->m_vpsNamesThatWereFilled.begin(), GAMESTATE->m_vpsNamesThatWereFilled.end(), psName ) != GAMESTATE->m_vpsNamesThatWereFilled.end();
}
else
{
hs.SetName( NO_SCORE_NAME );
}
m_textNames[l].SetText( hs.GetDisplayName() );
m_textScores[l].SetText( ssprintf("%09i",hs.GetScore()) );
m_textNames[l].SetDiffuse( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
m_textScores[l].SetDiffuse( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
if( bRecentHighScore )
{
m_textNames[l].SetEffectGlowBlink(0.1f);
m_textScores[l].SetEffectGlowBlink(0.1f);
}
else
{
m_textNames[l].StopEffect();
m_textScores[l].StopEffect();
}
}
}
return SECONDS_PER_PAGE;
case RankingType_SpecificTrail:
{
m_textCourseTitle.SetText( pts.pCourse->GetDisplayFullTitle() );
m_Banner.LoadFromCourse( pts.pCourse );
const HighScoreList &hsl = PROFILEMAN->GetMachineProfile()->GetCourseHighScoreList( pts.pCourse, pts.pTrail );
for( int l=0; l<NUM_RANKING_LINES; l++ )
{
HighScore hs;
bool bRecentHighScore = false;
if( l < (int)hsl.vHighScores.size() )
{
hs = hsl.vHighScores[l];
const RString *psName = hsl.vHighScores[l].GetNameMutable();
bRecentHighScore = find( GAMESTATE->m_vpsNamesThatWereFilled.begin(), GAMESTATE->m_vpsNamesThatWereFilled.end(), psName ) != GAMESTATE->m_vpsNamesThatWereFilled.end();
}
else
{
hs.SetName( NO_SCORE_NAME );
}
m_textNames[l].SetText( hs.GetDisplayName() );
if( pts.pCourse->IsOni() )
{
m_textPoints[l].SetText( ssprintf("%04d",hs.GetScore()) );
m_textTime[l].SetText( SecondsToMMSSMsMs(hs.GetSurviveSeconds()) );
m_textScores[l].SetText( "" );
} else {
m_textPoints[l].SetText( "" );
m_textTime[l].SetText( "" );
m_textScores[l].SetText( ssprintf("%09d",hs.GetScore()) );
}
m_textNames[l].SetDiffuse( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
m_textPoints[l].SetDiffuse( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
m_textTime[l].SetDiffuse( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
m_textScores[l].SetDiffuse( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
if( bRecentHighScore )
{
m_textNames[l].SetEffectGlowBlink(0.1f);
m_textScores[l].SetEffectGlowBlink(0.1f);
}
else
{
m_textNames[l].StopEffect();
m_textScores[l].StopEffect();
}
}
}
return SECONDS_PER_PAGE;
default:
ASSERT(0);
return 0;
}
}
/*
* (c) 2001-2007 Chris Danford, Glenn Maynard
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "global.h"
#include "ScreenRanking.h"
#include "ScreenManager.h"
#include "SongManager.h"
#include "GameState.h"
#include "GameManager.h"
#include "ProfileManager.h"
#include "Profile.h"
static const char *RankingTypeNames[] = {
"Category",
"Course",
};
XToString( RankingType );
LuaXType( RankingType );
AutoScreenMessage( SM_ShowNextPage );
AutoScreenMessage( SM_HidePage );
REGISTER_SCREEN_CLASS( ScreenRanking );
#define BULLET_X(row) (BULLET_START_X+ROW_SPACING_X*row)
#define BULLET_Y(row) (BULLET_START_Y+ROW_SPACING_Y*row)
#define NAME_X(row) (NAME_START_X+ROW_SPACING_X*row)
#define NAME_Y(row) (NAME_START_Y+ROW_SPACING_Y*row)
#define SCORE_X(row) (SCORE_START_X+ROW_SPACING_X*row)
#define SCORE_Y(row) (SCORE_START_Y+ROW_SPACING_Y*row)
#define POINTS_X(row) (POINTS_START_X+ROW_SPACING_X*row)
#define POINTS_Y(row) (POINTS_START_Y+ROW_SPACING_Y*row)
#define TIME_X(row) (TIME_START_X+ROW_SPACING_X*row)
#define TIME_Y(row) (TIME_START_Y+ROW_SPACING_Y*row)
static RString STEPS_TYPE_COLOR_NAME( size_t i ) { return ssprintf("StepsTypeColor%d",int(i+1)); }
void ScreenRanking::Init()
{
STEPS_TYPES_TO_SHOW.Load( m_sName,"StepsTypesToHide" ); // tricky: The metric name is "hide" because ThemeMetricStepsTypesToShow takes a list of what to hide and returns what StepsTypes to show
PAGE_FADE_SECONDS.Load ( m_sName,"PageFadeSeconds" );
ScreenAttract::Init();
m_textStepsType.SetName( "StepsType" );
m_textStepsType.LoadFromFont( THEME->GetPathF(m_sName,"StepsType") );
m_textStepsType.SetShadowLength( 0 );
this->AddChild( &m_textStepsType );
LOAD_ALL_COMMANDS( m_textStepsType );
RANKING_TYPE.Load ( m_sName,"RankingType");
COURSES_TO_SHOW.Load ( m_sName,"CoursesToShow");
SECONDS_PER_PAGE.Load ( m_sName,"SecondsPerPage" );
NO_SCORE_NAME.Load( m_sName,"NoScoreName" );
ROW_SPACING_X.Load( m_sName,"RowSpacingX" );
ROW_SPACING_Y.Load( m_sName,"RowSpacingY" );
BULLET_START_X.Load( m_sName, "BulletStartX" );
BULLET_START_Y.Load( m_sName, "BulletStartY" );
NAME_START_X.Load( m_sName, "NameStartX" );
NAME_START_Y.Load( m_sName, "NameStartY" );
SCORE_START_X.Load( m_sName, "ScoreStartX" );
SCORE_START_Y.Load( m_sName, "ScoreStartY" );
POINTS_START_X.Load( m_sName, "PointsStartX" );
POINTS_START_Y.Load( m_sName, "PointsStartY" );
TIME_START_X.Load( m_sName, "TimeStartX" );
TIME_START_Y.Load( m_sName, "TimeStartY" );
STEPS_TYPE_COLOR.Load( m_sName,STEPS_TYPE_COLOR_NAME,NUM_RANKING_LINES );
if( RANKING_TYPE == RankingType_Category )
{
m_textCategory.SetName( "Category" );
m_textCategory.LoadFromFont( THEME->GetPathF(m_sName,"category") );
//m_textCategory.SetShadowLength( 0 );
this->AddChild( &m_textCategory );
LOAD_ALL_COMMANDS( m_textCategory );
for( unsigned i=0; i<STEPS_TYPES_TO_SHOW.GetValue().size(); i++ )
{
for( int c=0; c<NUM_RankingCategory; c++ )
{
PageToShow pts;
pts.colorIndex = i;
pts.category = (RankingCategory)c;
StepsType st = STEPS_TYPES_TO_SHOW.GetValue()[i];
pts.aTypes.push_back( make_pair(Difficulty_Invalid, st) );
m_vPagesToShow.push_back( pts );
}
}
}
if( RANKING_TYPE == RankingType_SpecificTrail )
{
m_Banner.SetName( "Banner" );
this->AddChild( &m_Banner );
LOAD_ALL_COMMANDS( m_Banner );
m_textCourseTitle.SetName( "CourseTitle" );
m_textCourseTitle.LoadFromFont( THEME->GetPathF(m_sName,"course title") );
//m_textCourseTitle.SetShadowLength( 0 );
this->AddChild( &m_textCourseTitle );
LOAD_ALL_COMMANDS( m_textCourseTitle );
vector<RString> asCoursePaths;
split( COURSES_TO_SHOW, ",", asCoursePaths, true );
for( unsigned i=0; i<STEPS_TYPES_TO_SHOW.GetValue().size(); i++ )
{
for( unsigned c=0; c<asCoursePaths.size(); c++ )
{
PageToShow pts;
pts.colorIndex = i;
StepsType st = STEPS_TYPES_TO_SHOW.GetValue()[i];
pts.aTypes.push_back( make_pair(Difficulty_Invalid, st) );
pts.pCourse = SONGMAN->GetCourseFromPath( asCoursePaths[c] );
if( pts.pCourse == NULL )
continue;
pts.pTrail = pts.pCourse->GetTrail( st );
if( pts.pTrail == NULL )
continue;
m_vPagesToShow.push_back( pts );
}
}
}
for( int l=0; l<NUM_RANKING_LINES; l++ )
{
m_sprBullets[l].Load( THEME->GetPathG( m_sName, ssprintf("bullets 1x%d",NUM_RANKING_LINES) ) );
m_sprBullets[l]->SetName( ssprintf("Bullet%d",l+1) );
m_sprBullets[l]->StopAnimating();
m_sprBullets[l]->SetState( l );
m_sprBullets[l]->SetXY( BULLET_X(l), BULLET_Y(l) );
ActorUtil::LoadAllCommands( *m_sprBullets[l], m_sName );
this->AddChild( m_sprBullets[l] );
m_textNames[l].SetName( ssprintf("Name%d",l+1) );
m_textNames[l].LoadFromFont( THEME->GetPathF(m_sName,"name") );
m_textNames[l].SetXY( NAME_X(l), NAME_Y(l) );
ActorUtil::LoadAllCommands( m_textNames[l], m_sName );
this->AddChild( &m_textNames[l] );
m_textScores[l].SetName( ssprintf("Score%d",l+1) );
m_textScores[l].LoadFromFont( THEME->GetPathF(m_sName,"score") );
m_textScores[l].SetXY( SCORE_X(l), SCORE_Y(l) );
ActorUtil::LoadAllCommands( m_textScores[l], m_sName );
this->AddChild( &m_textScores[l] );
m_textPoints[l].SetName( ssprintf("Points%d",l+1) );
m_textPoints[l].LoadFromFont( THEME->GetPathF(m_sName,"points") );
m_textPoints[l].SetVisible( false );
m_textPoints[l].SetXY( POINTS_X(l), POINTS_Y(l) );
ActorUtil::LoadAllCommands( m_textPoints[l], m_sName );
this->AddChild( &m_textPoints[l] );
m_textTime[l].SetName( ssprintf("Time%d",l+1) );
m_textTime[l].LoadFromFont( THEME->GetPathF(m_sName,"time") );
m_textTime[l].SetVisible( false );
m_textTime[l].SetXY( TIME_X(l), TIME_Y(l) );
ActorUtil::LoadAllCommands( m_textTime[l], m_sName );
this->AddChild( &m_textTime[l] );
}
}
void ScreenRanking::BeginScreen()
{
m_iNextPageToShow = 0;
ScreenAttract::BeginScreen();
this->HandleScreenMessage( SM_ShowNextPage );
}
void ScreenRanking::HandleScreenMessage( const ScreenMessage SM )
{
if( SM == SM_ShowNextPage )
{
if( m_iNextPageToShow < m_vPagesToShow.size() )
{
float fSecsToShow = SetPage( m_vPagesToShow[m_iNextPageToShow] );
++m_iNextPageToShow;
this->SortByDrawOrder();
this->PlayCommand( "NextPage" );
this->PostScreenMessage( SM_HidePage, fSecsToShow-PAGE_FADE_SECONDS );
}
else
{
StartTransitioningScreen(SM_GoToNextScreen);
}
}
else if( SM == SM_HidePage )
{
this->PlayCommand( "SwitchedPage" );
this->PostScreenMessage( SM_ShowNextPage, PAGE_FADE_SECONDS );
}
ScreenAttract::HandleScreenMessage( SM );
}
float ScreenRanking::SetPage( const PageToShow &pts )
{
// This is going to take a while to load. Possibly longer than one frame.
// So, zero the next update so we don't skip.
SCREENMAN->ZeroNextUpdate();
// init page
StepsType st = pts.aTypes.front().second;
m_textStepsType.SetText( GAMEMAN->GetStepsTypeInfo(st).GetLocalizedString() );
bool bShowScores = false;
bool bShowPoints = false;
bool bShowTime = false;
switch( RANKING_TYPE )
{
case RankingType_Category:
bShowScores = true;
break;
case RankingType_SpecificTrail:
bShowScores = !pts.pCourse->IsOni();
bShowPoints = pts.pCourse->IsOni();
bShowTime = pts.pCourse->IsOni();
break;
default: break;
}
for( int l=0; l<NUM_RANKING_LINES; l++ )
{
m_textNames[l].SetDiffuseColor( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
m_textScores[l].SetVisible( bShowScores );
m_textScores[l].SetDiffuseColor( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
m_textPoints[l].SetVisible( bShowPoints );
m_textPoints[l].SetDiffuseColor( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
m_textTime[l].SetVisible( bShowTime );
m_textTime[l].SetDiffuseColor( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
}
switch( RANKING_TYPE )
{
case RankingType_Category:
{
m_textCategory.SetText( ssprintf("Type %c", 'A'+pts.category) );
for( int l=0; l<NUM_RANKING_LINES; l++ )
{
// No need to shadow at this point.
st = pts.aTypes.front().second;
HighScoreList &hsl = PROFILEMAN->GetMachineProfile()->GetCategoryHighScoreList(st, pts.category);
HighScore hs;
bool bRecentHighScore = false;
if( l < (int)hsl.vHighScores.size() )
{
hs = hsl.vHighScores[l];
RString *psName = hsl.vHighScores[l].GetNameMutable();
bRecentHighScore = find( GAMESTATE->m_vpsNamesThatWereFilled.begin(), GAMESTATE->m_vpsNamesThatWereFilled.end(), psName ) != GAMESTATE->m_vpsNamesThatWereFilled.end();
}
else
{
hs.SetName( NO_SCORE_NAME );
}
m_textNames[l].SetText( hs.GetDisplayName() );
m_textScores[l].SetText( ssprintf("%09i",hs.GetScore()) );
m_textNames[l].SetDiffuseColor( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
m_textScores[l].SetDiffuseColor( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
if( bRecentHighScore )
{
m_textNames[l].SetEffectGlowBlink(0.1f);
m_textScores[l].SetEffectGlowBlink(0.1f);
}
else
{
m_textNames[l].StopEffect();
m_textScores[l].StopEffect();
}
}
}
return SECONDS_PER_PAGE;
case RankingType_SpecificTrail:
{
m_textCourseTitle.SetText( pts.pCourse->GetDisplayFullTitle() );
m_Banner.LoadFromCourse( pts.pCourse );
const HighScoreList &hsl = PROFILEMAN->GetMachineProfile()->GetCourseHighScoreList( pts.pCourse, pts.pTrail );
for( int l=0; l<NUM_RANKING_LINES; l++ )
{
HighScore hs;
bool bRecentHighScore = false;
if( l < (int)hsl.vHighScores.size() )
{
hs = hsl.vHighScores[l];
const RString *psName = hsl.vHighScores[l].GetNameMutable();
bRecentHighScore = find( GAMESTATE->m_vpsNamesThatWereFilled.begin(), GAMESTATE->m_vpsNamesThatWereFilled.end(), psName ) != GAMESTATE->m_vpsNamesThatWereFilled.end();
}
else
{
hs.SetName( NO_SCORE_NAME );
}
m_textNames[l].SetText( hs.GetDisplayName() );
if( pts.pCourse->IsOni() )
{
m_textPoints[l].SetText( ssprintf("%04d",hs.GetScore()) );
m_textTime[l].SetText( SecondsToMMSSMsMs(hs.GetSurviveSeconds()) );
m_textScores[l].SetText( "" );
} else {
m_textPoints[l].SetText( "" );
m_textTime[l].SetText( "" );
m_textScores[l].SetText( ssprintf("%09d",hs.GetScore()) );
}
m_textNames[l].SetDiffuseColor( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
m_textPoints[l].SetDiffuseColor( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
m_textTime[l].SetDiffuseColor( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
m_textScores[l].SetDiffuseColor( STEPS_TYPE_COLOR.GetValue(pts.colorIndex) );
if( bRecentHighScore )
{
m_textNames[l].SetEffectGlowBlink(0.1f);
m_textScores[l].SetEffectGlowBlink(0.1f);
}
else
{
m_textNames[l].StopEffect();
m_textScores[l].StopEffect();
}
}
}
return SECONDS_PER_PAGE;
default:
ASSERT(0);
return 0;
}
}
/*
* (c) 2001-2007 Chris Danford, Glenn Maynard
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
+2045 -2038
View File
File diff suppressed because it is too large Load Diff
+479 -475
View File
@@ -1,475 +1,479 @@
#ifndef SONG_H
#define SONG_H
#include "Attack.h"
#include "TimingData.h"
#include "Difficulty.h"
#include "EnumHelper.h"
#include "RageUtil_AutoPtr.h"
#include "RageUtil_CachedObject.h"
#include "RageTypes.h"
#include "Steps.h"
#include <set>
class Style;
class StepsID;
struct lua_State;
struct BackgroundChange;
void FixupPath( RString &path, const RString &sSongPath );
RString GetSongAssetPath( RString sPath, const RString &sSongPath );
/** @brief The version of the .ssc file format. */
const static float STEPFILE_VERSION_NUMBER = 0.81f;
/** @brief How many edits for this song can each profile have? */
const int MAX_EDITS_PER_SONG_PER_PROFILE = 15;
/** @brief How many edits for this song can be available? */
const int MAX_EDITS_PER_SONG = MAX_EDITS_PER_SONG_PER_PROFILE * NUM_ProfileSlot;
extern const int FILE_CACHE_VERSION;
/** @brief The different background layers available. */
enum BackgroundLayer
{
BACKGROUND_LAYER_1,
BACKGROUND_LAYER_2,
//BACKGROUND_LAYER_3, // StepCollection get
NUM_BackgroundLayer,
BACKGROUND_LAYER_Invalid
};
/** @brief A custom foreach loop for the different background layers. */
#define FOREACH_BackgroundLayer( bl ) FOREACH_ENUM( BackgroundLayer, bl )
/** @brief Different instrument tracks for band type games. */
enum InstrumentTrack
{
InstrumentTrack_Guitar,
InstrumentTrack_Rhythm,
InstrumentTrack_Bass,
NUM_InstrumentTrack,
InstrumentTrack_Invalid
};
const RString& InstrumentTrackToString( InstrumentTrack it );
InstrumentTrack StringToInstrumentTrack( const RString& s );
/** @brief The collection of lyrics for the Song. */
struct LyricSegment
{
float m_fStartTime; /** @brief When does the lyric show up? */
RString m_sLyric; /** @brief The lyrics themselves. */
RageColor m_Color; /** @brief The color of the lyrics. */
};
/** @brief Holds all music metadata and steps for one song. */
class Song
{
RString m_sSongDir;
public:
void SetSongDir( const RString sDir ) { m_sSongDir = sDir; }
RString GetSongDir() { return m_sSongDir; }
/** @brief When should this song be displayed in the music wheel? */
enum SelectionDisplay
{
SHOW_ALWAYS, /**< always show on the wheel. */
SHOW_NEVER /**< never show on the wheel (unless song hiding is turned off). */
} m_SelectionDisplay;
Song();
~Song();
void Reset();
void DetachSteps();
/**
* @brief Load a song from the chosen directory.
*
* This assumes that there is no song present right now.
* @param sDir the song directory from which to load. */
bool LoadFromSongDir( RString sDir );
// This one takes the effort to reuse Steps pointers as best as it can
bool ReloadFromSongDir( RString sDir );
/**
* @brief Call this after loading a song to clean up invalid data.
* @param fromCache was this data loaded from the cache file?
* @param duringCache was this data loaded during the cache process? */
void TidyUpData( bool fromCache = false, bool duringCache = false );
/**
* @brief Get the new radar values, and determine the last second at the same time.
* This is called by TidyUpData, after saving the Song.
* @param fromCache was this data loaded from the cache file?
* @param duringCache was this data loaded during the cache process? */
void ReCalculateRadarValuesAndLastSecond(bool fromCache = false, bool duringCache = false);
/**
* @brief Translate any titles that aren't in english.
* This is called by TidyUpData. */
void TranslateTitles();
/**
* @brief Save to the new SSC file format.
* @param sPath the path where we're saving the file.
* @param bSavingCache a flag to determine if we're saving cache data.
*/
bool SaveToSSCFile( RString sPath, bool bSavingCache );
/** @brief Save to the SSC and SM files no matter what. */
void Save();
/**
* @brief Save the current Song to a cache file using the preferred format.
* @return its success or failure. */
bool SaveToCacheFile();
/**
* @brief Save the current Song to a SM file.
* @return its success or failure. */
bool SaveToSMFile();
/**
* @brief Save the current Song to a DWI file if possible.
* @return its success or failure. */
bool SaveToDWIFile();
const RString &GetSongFilePath() const;
RString GetCacheFilePath() const;
void AddAutoGenNotes();
/**
* @brief Automatically generate steps from one type to another.
* @param ntTo the StepsType we're making.
* @param ntFrom the StepsType we're generating from.
*/
void AutoGen( StepsType ntTo, StepsType ntFrom );
void RemoveAutoGenNotes();
// Directory this song data came from:
const RString &GetSongDir() const { return m_sSongDir; }
/**
* @brief Filename associated with this file.
* This will always have a .SSC extension. If we loaded a .SSC, this will
* point to it, but if we loaded any other type, this will point to
* a generated .SSC filename. */
RString m_sSongFileName;
/** @brief The group this Song is in. */
RString m_sGroupName;
/**
* @brief the Profile this came from.
* This is ProfileSlot_Invalid if it wasn't loaded from a profile. */
ProfileSlot m_LoadedFromProfile;
/** @brief Is the song file itself a symlink to another file? */
bool m_bIsSymLink;
bool m_bEnabled;
/** @brief The title of the Song. */
RString m_sMainTitle;
/** @brief The subtitle of the Song, if it exists. */
RString m_sSubTitle;
/** @brief The artist of the Song, if it exists. */
RString m_sArtist;
/** @brief The transliterated title of the Song, if it exists. */
RString m_sMainTitleTranslit;
/** @brief The transliterated subtitle of the Song, if it exists. */
RString m_sSubTitleTranslit;
/** @brief The transliterated artist of the Song, if it exists. */
RString m_sArtistTranslit;
/* If PREFSMAN->m_bShowNative is off, these are the same as GetTranslit*
* below. Otherwise, they return the main titles. */
RString GetDisplayMainTitle() const;
RString GetDisplaySubTitle() const;
RString GetDisplayArtist() const;
/**
* @brief Retrieve the transliterated title, or the main title if there is no translit.
* @return the proper title. */
RString GetTranslitMainTitle() const
{
return m_sMainTitleTranslit.size()? m_sMainTitleTranslit: m_sMainTitle;
}
/**
* @brief Retrieve the transliterated subtitle, or the main subtitle if there is no translit.
* @return the proper subtitle. */
RString GetTranslitSubTitle() const
{
return m_sSubTitleTranslit.size()? m_sSubTitleTranslit: m_sSubTitle;
}
/**
* @brief Retrieve the transliterated artist, or the main artist if there is no translit.
* @return the proper artist. */
RString GetTranslitArtist() const
{
return m_sArtistTranslit.size()? m_sArtistTranslit:m_sArtist;
}
// "title subtitle"
RString GetDisplayFullTitle() const;
RString GetTranslitFullTitle() const;
/** @brief The version of the song/file. */
float m_fVersion;
/** @brief The genre of the song/file. */
RString m_sGenre;
/**
* @brief The person who worked with the song file who should be credited.
* This is read and saved, but never actually used. */
RString m_sCredit;
RString m_sOrigin; // song origin (for .ssc format)
RString m_sMusicFile;
RString m_sInstrumentTrackFile[NUM_InstrumentTrack];
/** @brief The length of the music file. */
float m_fMusicLengthSeconds;
float m_fMusicSampleStartSeconds;
float m_fMusicSampleLengthSeconds;
DisplayBPM m_DisplayBPMType;
float m_fSpecifiedBPMMin;
float m_fSpecifiedBPMMax; // if a range, then Min != Max
RString m_sBannerFile; // typically a 16:5 ratio graphic (e.g. 256x80)
RString m_sJacketFile; // typically square (e.g. 192x192, 256x256)
RString m_sCDFile; // square (e.g. 128x128 [DDR 1st-3rd])
RString m_sDiscFile; // rectangular (e.g. 256x192 [Pump], 200x150 [MGD3])
/** @brief The location of the lyrics file, if it exists. */
RString m_sLyricsFile;
RString m_sBackgroundFile;
RString m_sCDTitleFile;
RString m_sPreviewVidFile;
AttackArray m_Attacks;
vector<RString> m_sAttackString;
RString GetMusicPath() const;
RString GetInstrumentTrackPath( InstrumentTrack it ) const;
RString GetBannerPath() const;
RString GetJacketPath() const;
RString GetCDImagePath() const;
RString GetDiscPath() const;
RString GetLyricsPath() const;
RString GetBackgroundPath() const;
RString GetCDTitlePath() const;
RString GetPreviewVidPath() const;
// For loading only:
bool m_bHasMusic, m_bHasBanner, m_bHasBackground;
bool HasMusic() const;
bool HasInstrumentTrack( InstrumentTrack it ) const;
/**
* @brief Does this song have a banner?
* @return true if it does, false otherwise. */
bool HasBanner() const;
/**
* @brief Does this song have a background image?
* @return true if it does, false otherwise. */
bool HasBackground() const;
bool HasJacket() const;
bool HasCDImage() const;
bool HasDisc() const;
bool HasCDTitle() const;
//bool HasMovieBackground() const;
bool HasBGChanges() const;
bool HasLyrics() const;
bool HasAttacks() const;
bool HasPreviewVid() const;
bool Matches(RString sGroup, RString sSong) const;
/** @brief The Song's TimingData. */
TimingData m_SongTiming;
float GetFirstBeat() const;
float GetFirstSecond() const;
float GetLastBeat() const;
float GetLastSecond() const;
float GetSpecifiedLastBeat() const;
float GetSpecifiedLastSecond() const;
void SetFirstSecond(const float f);
void SetLastSecond(const float f);
void SetSpecifiedLastSecond(const float f);
typedef vector<BackgroundChange> VBackgroundChange;
private:
/** @brief The first second that a note is hit. */
float firstSecond;
/** @brief The last second that a note is hit. */
float lastSecond;
/** @brief The last second of the song for playing purposes. */
float specifiedLastSecond;
/**
* @brief The background changes (sorted by layer) that are for this Song.
* This uses an AutoPtr instead of a raw pointer so that the
* auto gen'd copy constructor works correctly.
* This must be sorted before gameplay. */
AutoPtrCopyOnWrite<VBackgroundChange> m_BackgroundChanges[NUM_BackgroundLayer];
/**
* @brief The foreground changes that are for this Song.
* This uses an AutoPtr instead of a raw pointer so that the
* auto gen'd copy constructor works correctly.
* This must be sorted before gameplay. */
AutoPtrCopyOnWrite<VBackgroundChange> m_ForegroundChanges;
vector<RString> GetChangesToVectorString(const vector<BackgroundChange> & changes) const;
public:
const vector<BackgroundChange> &GetBackgroundChanges( BackgroundLayer bl ) const;
vector<BackgroundChange> &GetBackgroundChanges( BackgroundLayer bl );
const vector<BackgroundChange> &GetForegroundChanges() const;
vector<BackgroundChange> &GetForegroundChanges();
vector<RString> GetBGChanges1ToVectorString() const;
vector<RString> GetBGChanges2ToVectorString() const;
vector<RString> GetFGChanges1ToVectorString() const;
vector<RString> GetInstrumentTracksToVectorString() const;
/**
* @brief The list of LyricSegments.
* This must be sorted before gameplay. */
vector<LyricSegment> m_LyricSegments;
/* [splittiming]
void AddBPMSegment( const BPMSegment &seg ) { m_Timing.AddBPMSegment( seg ); }
void AddStopSegment( const StopSegment &seg ) { m_Timing.AddStopSegment( seg ); }
void AddWarpSegment( const WarpSegment &seg ) { m_Timing.AddWarpSegment( seg ); }
*/
void AddBackgroundChange( BackgroundLayer blLayer, BackgroundChange seg );
void AddForegroundChange( BackgroundChange seg );
void AddLyricSegment( LyricSegment seg );
void GetDisplayBpms( DisplayBpms &AddTo ) const;
const BackgroundChange &GetBackgroundAtBeat( BackgroundLayer iLayer, float fBeat ) const;
/* [splittiming]
float GetBPMAtBeat( float fBeat ) const { return m_Timing.GetBPMAtBeat( fBeat ); }
void SetBPMAtBeat( float fBeat, float fBPM ) { m_Timing.SetBPMAtBeat( fBeat, fBPM ); }
BPMSegment& GetBPMSegmentAtBeat( float fBeat ) { return m_Timing.GetBPMSegmentAtBeat( fBeat ); }
*/
Steps *CreateSteps();
void InitSteps(Steps *pSteps);
/* [splittiming]
float SongGetBeatFromElapsedTime( float fElapsedTime ) const
{
return m_SongTiming.GetBeatFromElapsedTime( fElapsedTime );
}
float StepsGetBeatFromElapsedTime( float fElapsedTime, const Steps &steps ) const
{
return steps.m_Timing.GetBeatFromElapsedTime( fElapsedTime );
}
float SongGetElapsedTimeFromBeat( float fBeat ) const
{
return m_SongTiming.GetElapsedTimeFromBeat( fBeat );
}
float StepsGetElapsedTimeFromBeat( float fBeat, const Steps &steps ) const
{
return steps.m_Timing.GetElapsedTimeFromBeat( fBeat );
}
*/
/* [splittiming]
float GetBeatFromElapsedTime( float fElapsedTime ) const
{
return m_Timing.GetBeatFromElapsedTime( fElapsedTime );
}
float GetElapsedTimeFromBeat( float fBeat ) const { return m_Timing.GetElapsedTimeFromBeat( fBeat ); }
*/
bool HasSignificantBpmChangesOrStops() const;
float GetStepsSeconds() const;
bool IsLong() const;
bool IsMarathon() const;
bool SongCompleteForStyle( const Style *st ) const;
bool HasStepsType( StepsType st ) const;
bool HasStepsTypeAndDifficulty( StepsType st, Difficulty dc ) const;
const vector<Steps*>& GetAllSteps() const { return m_vpSteps; }
const vector<Steps*>& GetStepsByStepsType( StepsType st ) const { return m_vpStepsByType[st]; }
bool IsEasy( StepsType st ) const;
bool IsTutorial() const;
bool HasEdits( StepsType st ) const;
void SetEnabled( bool b ) { m_bEnabled = b; }
bool GetEnabled() const { return m_bEnabled; }
/**
* @brief Determine if the song should be shown on the MusicWheel normally.
* Songs that are not displayed normally may still be available during
* random selection, extra stages, or other special conditions.
* @return true if displayed normally, false otherwise. */
bool NormallyDisplayed() const;
bool ShowInDemonstrationAndRanking() const;
/**
* @brief Add the chosen Steps to the Song.
* We are responsible for deleting the memory pointed to by pSteps!
* @param pSteps the new steps. */
void AddSteps( Steps* pSteps );
void DeleteSteps( const Steps* pSteps, bool bReAutoGen = true );
void FreeAllLoadedFromProfile( ProfileSlot slot = ProfileSlot_Invalid, const set<Steps*> *setInUse = NULL );
bool WasLoadedFromProfile() const { return m_LoadedFromProfile != ProfileSlot_Invalid; }
void GetStepsLoadedFromProfile( ProfileSlot slot, vector<Steps*> &vpStepsOut ) const;
int GetNumStepsLoadedFromProfile( ProfileSlot slot ) const;
bool IsEditAlreadyLoaded( Steps* pSteps ) const;
bool IsStepsUsingDifferentTiming(Steps *pSteps ) const;
/**
* @brief An array of keysound file names (e.g. "beep.wav").
* The index in this array corresponds to the index in TapNote.
* If you change the index in here, you must change all NoteData too.
* Any note that doesn't have a value in the range of this array
* means "this note doesn't have a keysound". */
vector<RString> m_vsKeysoundFile;
CachedObject<Song> m_CachedObject;
RString GetAttackString() const
{
return join(":", this->m_sAttackString);
}
// Lua
void PushSelf( lua_State *L );
private:
/** @brief the Steps that belong to this Song. */
vector<Steps*> m_vpSteps;
/** @brief the Steps of a particular StepsType that belong to this Song. */
vector<Steps*> m_vpStepsByType[NUM_StepsType];
};
#endif
/**
* @file
* @author Chris Danford, Glenn Maynard (c) 2001-2004
* @section LICENSE
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef SONG_H
#define SONG_H
#include "Attack.h"
#include "TimingData.h"
#include "Difficulty.h"
#include "EnumHelper.h"
#include "RageUtil_AutoPtr.h"
#include "RageUtil_CachedObject.h"
#include "RageTypes.h"
#include "Steps.h"
#include <set>
class Style;
class StepsID;
struct lua_State;
struct BackgroundChange;
void FixupPath( RString &path, const RString &sSongPath );
RString GetSongAssetPath( RString sPath, const RString &sSongPath );
/** @brief The version of the .ssc file format. */
const static float STEPFILE_VERSION_NUMBER = 0.81f;
/** @brief How many edits for this song can each profile have? */
const int MAX_EDITS_PER_SONG_PER_PROFILE = 15;
/** @brief How many edits for this song can be available? */
const int MAX_EDITS_PER_SONG = MAX_EDITS_PER_SONG_PER_PROFILE * NUM_ProfileSlot;
extern const int FILE_CACHE_VERSION;
/** @brief The different background layers available. */
enum BackgroundLayer
{
BACKGROUND_LAYER_1,
BACKGROUND_LAYER_2,
//BACKGROUND_LAYER_3, // StepCollection get
NUM_BackgroundLayer,
BACKGROUND_LAYER_Invalid
};
/** @brief A custom foreach loop for the different background layers. */
#define FOREACH_BackgroundLayer( bl ) FOREACH_ENUM( BackgroundLayer, bl )
/** @brief Different instrument tracks for band type games. */
enum InstrumentTrack
{
InstrumentTrack_Guitar,
InstrumentTrack_Rhythm,
InstrumentTrack_Bass,
NUM_InstrumentTrack,
InstrumentTrack_Invalid
};
const RString& InstrumentTrackToString( InstrumentTrack it );
InstrumentTrack StringToInstrumentTrack( const RString& s );
/** @brief The collection of lyrics for the Song. */
struct LyricSegment
{
float m_fStartTime; /** @brief When does the lyric show up? */
RString m_sLyric; /** @brief The lyrics themselves. */
RageColor m_Color; /** @brief The color of the lyrics. */
};
/** @brief Holds all music metadata and steps for one song. */
class Song
{
RString m_sSongDir;
public:
void SetSongDir( const RString sDir ) { m_sSongDir = sDir; }
RString GetSongDir() { return m_sSongDir; }
/** @brief When should this song be displayed in the music wheel? */
enum SelectionDisplay
{
SHOW_ALWAYS, /**< always show on the wheel. */
SHOW_NEVER /**< never show on the wheel (unless song hiding is turned off). */
} m_SelectionDisplay;
Song();
~Song();
void Reset();
void DetachSteps();
/**
* @brief Load a song from the chosen directory.
*
* This assumes that there is no song present right now.
* @param sDir the song directory from which to load. */
bool LoadFromSongDir( RString sDir );
// This one takes the effort to reuse Steps pointers as best as it can
bool ReloadFromSongDir( RString sDir );
/**
* @brief Call this after loading a song to clean up invalid data.
* @param fromCache was this data loaded from the cache file?
* @param duringCache was this data loaded during the cache process? */
void TidyUpData( bool fromCache = false, bool duringCache = false );
/**
* @brief Get the new radar values, and determine the last second at the same time.
* This is called by TidyUpData, after saving the Song.
* @param fromCache was this data loaded from the cache file?
* @param duringCache was this data loaded during the cache process? */
void ReCalculateRadarValuesAndLastSecond(bool fromCache = false, bool duringCache = false);
/**
* @brief Translate any titles that aren't in english.
* This is called by TidyUpData. */
void TranslateTitles();
/**
* @brief Save to the new SSC file format.
* @param sPath the path where we're saving the file.
* @param bSavingCache a flag to determine if we're saving cache data.
*/
bool SaveToSSCFile( RString sPath, bool bSavingCache );
/** @brief Save to the SSC and SM files no matter what. */
void Save();
/**
* @brief Save the current Song to a JSON file.
* @return its success or failure. */
bool SaveToJsonFile( RString sPath );
/**
* @brief Save the current Song to a cache file using the preferred format.
* @return its success or failure. */
bool SaveToCacheFile();
/**
* @brief Save the current Song to a SM file.
* @return its success or failure. */
bool SaveToSMFile();
/**
* @brief Save the current Song to a DWI file if possible.
* @return its success or failure. */
bool SaveToDWIFile();
const RString &GetSongFilePath() const;
RString GetCacheFilePath() const;
void AddAutoGenNotes();
/**
* @brief Automatically generate steps from one type to another.
* @param ntTo the StepsType we're making.
* @param ntFrom the StepsType we're generating from.
*/
void AutoGen( StepsType ntTo, StepsType ntFrom );
void RemoveAutoGenNotes();
// Directory this song data came from:
const RString &GetSongDir() const { return m_sSongDir; }
/**
* @brief Filename associated with this file.
* This will always have a .SSC extension. If we loaded a .SSC, this will
* point to it, but if we loaded any other type, this will point to
* a generated .SSC filename. */
RString m_sSongFileName;
/** @brief The group this Song is in. */
RString m_sGroupName;
/**
* @brief the Profile this came from.
* This is ProfileSlot_Invalid if it wasn't loaded from a profile. */
ProfileSlot m_LoadedFromProfile;
/** @brief Is the song file itself a symlink to another file? */
bool m_bIsSymLink;
bool m_bEnabled;
/** @brief The title of the Song. */
RString m_sMainTitle;
/** @brief The subtitle of the Song, if it exists. */
RString m_sSubTitle;
/** @brief The artist of the Song, if it exists. */
RString m_sArtist;
/** @brief The transliterated title of the Song, if it exists. */
RString m_sMainTitleTranslit;
/** @brief The transliterated subtitle of the Song, if it exists. */
RString m_sSubTitleTranslit;
/** @brief The transliterated artist of the Song, if it exists. */
RString m_sArtistTranslit;
/* If PREFSMAN->m_bShowNative is off, these are the same as GetTranslit*
* below. Otherwise, they return the main titles. */
RString GetDisplayMainTitle() const;
RString GetDisplaySubTitle() const;
RString GetDisplayArtist() const;
/**
* @brief Retrieve the transliterated title, or the main title if there is no translit.
* @return the proper title. */
RString GetTranslitMainTitle() const
{
return m_sMainTitleTranslit.size()? m_sMainTitleTranslit: m_sMainTitle;
}
/**
* @brief Retrieve the transliterated subtitle, or the main subtitle if there is no translit.
* @return the proper subtitle. */
RString GetTranslitSubTitle() const
{
return m_sSubTitleTranslit.size()? m_sSubTitleTranslit: m_sSubTitle;
}
/**
* @brief Retrieve the transliterated artist, or the main artist if there is no translit.
* @return the proper artist. */
RString GetTranslitArtist() const
{
return m_sArtistTranslit.size()? m_sArtistTranslit:m_sArtist;
}
// "title subtitle"
RString GetDisplayFullTitle() const;
RString GetTranslitFullTitle() const;
/** @brief The version of the song/file. */
float m_fVersion;
/** @brief The genre of the song/file. */
RString m_sGenre;
/**
* @brief The person who worked with the song file who should be credited.
* This is read and saved, but never actually used. */
RString m_sCredit;
RString m_sOrigin; // song origin (for .ssc format)
RString m_sMusicFile;
RString m_sInstrumentTrackFile[NUM_InstrumentTrack];
/** @brief The length of the music file. */
float m_fMusicLengthSeconds;
float m_fMusicSampleStartSeconds;
float m_fMusicSampleLengthSeconds;
DisplayBPM m_DisplayBPMType;
float m_fSpecifiedBPMMin;
float m_fSpecifiedBPMMax; // if a range, then Min != Max
RString m_sBannerFile; // typically a 16:5 ratio graphic (e.g. 256x80)
RString m_sJacketFile; // typically square (e.g. 192x192, 256x256)
RString m_sCDFile; // square (e.g. 128x128 [DDR 1st-3rd])
RString m_sDiscFile; // rectangular (e.g. 256x192 [Pump], 200x150 [MGD3])
/** @brief The location of the lyrics file, if it exists. */
RString m_sLyricsFile;
RString m_sBackgroundFile;
RString m_sCDTitleFile;
RString m_sPreviewVidFile;
AttackArray m_Attacks;
vector<RString> m_sAttackString;
RString GetMusicPath() const;
RString GetInstrumentTrackPath( InstrumentTrack it ) const;
RString GetBannerPath() const;
RString GetJacketPath() const;
RString GetCDImagePath() const;
RString GetDiscPath() const;
RString GetLyricsPath() const;
RString GetBackgroundPath() const;
RString GetCDTitlePath() const;
RString GetPreviewVidPath() const;
// For loading only:
bool m_bHasMusic, m_bHasBanner, m_bHasBackground;
bool HasMusic() const;
bool HasInstrumentTrack( InstrumentTrack it ) const;
/**
* @brief Does this song have a banner?
* @return true if it does, false otherwise. */
bool HasBanner() const;
/**
* @brief Does this song have a background image?
* @return true if it does, false otherwise. */
bool HasBackground() const;
bool HasJacket() const;
bool HasCDImage() const;
bool HasDisc() const;
bool HasCDTitle() const;
//bool HasMovieBackground() const;
bool HasBGChanges() const;
bool HasLyrics() const;
bool HasAttacks() const;
bool HasPreviewVid() const;
bool Matches(RString sGroup, RString sSong) const;
/** @brief The Song's TimingData. */
TimingData m_SongTiming;
float GetFirstBeat() const;
float GetFirstSecond() const;
float GetLastBeat() const;
float GetLastSecond() const;
float GetSpecifiedLastBeat() const;
float GetSpecifiedLastSecond() const;
void SetFirstSecond(const float f);
void SetLastSecond(const float f);
void SetSpecifiedLastSecond(const float f);
typedef vector<BackgroundChange> VBackgroundChange;
private:
/** @brief The first second that a note is hit. */
float firstSecond;
/** @brief The last second that a note is hit. */
float lastSecond;
/** @brief The last second of the song for playing purposes. */
float specifiedLastSecond;
/**
* @brief The background changes (sorted by layer) that are for this Song.
* This uses an AutoPtr instead of a raw pointer so that the
* auto gen'd copy constructor works correctly.
* This must be sorted before gameplay. */
AutoPtrCopyOnWrite<VBackgroundChange> m_BackgroundChanges[NUM_BackgroundLayer];
/**
* @brief The foreground changes that are for this Song.
* This uses an AutoPtr instead of a raw pointer so that the
* auto gen'd copy constructor works correctly.
* This must be sorted before gameplay. */
AutoPtrCopyOnWrite<VBackgroundChange> m_ForegroundChanges;
vector<RString> GetChangesToVectorString(const vector<BackgroundChange> & changes) const;
public:
const vector<BackgroundChange> &GetBackgroundChanges( BackgroundLayer bl ) const;
vector<BackgroundChange> &GetBackgroundChanges( BackgroundLayer bl );
const vector<BackgroundChange> &GetForegroundChanges() const;
vector<BackgroundChange> &GetForegroundChanges();
vector<RString> GetBGChanges1ToVectorString() const;
vector<RString> GetBGChanges2ToVectorString() const;
vector<RString> GetFGChanges1ToVectorString() const;
vector<RString> GetInstrumentTracksToVectorString() const;
/**
* @brief The list of LyricSegments.
* This must be sorted before gameplay. */
vector<LyricSegment> m_LyricSegments;
/* [splittiming]
void AddBPMSegment( const BPMSegment &seg ) { m_Timing.AddBPMSegment( seg ); }
void AddStopSegment( const StopSegment &seg ) { m_Timing.AddStopSegment( seg ); }
void AddWarpSegment( const WarpSegment &seg ) { m_Timing.AddWarpSegment( seg ); }
*/
void AddBackgroundChange( BackgroundLayer blLayer, BackgroundChange seg );
void AddForegroundChange( BackgroundChange seg );
void AddLyricSegment( LyricSegment seg );
void GetDisplayBpms( DisplayBpms &AddTo ) const;
const BackgroundChange &GetBackgroundAtBeat( BackgroundLayer iLayer, float fBeat ) const;
/* [splittiming]
float GetBPMAtBeat( float fBeat ) const { return m_Timing.GetBPMAtBeat( fBeat ); }
void SetBPMAtBeat( float fBeat, float fBPM ) { m_Timing.SetBPMAtBeat( fBeat, fBPM ); }
BPMSegment& GetBPMSegmentAtBeat( float fBeat ) { return m_Timing.GetBPMSegmentAtBeat( fBeat ); }
*/
Steps *CreateSteps();
void InitSteps(Steps *pSteps);
/* [splittiming]
float SongGetBeatFromElapsedTime( float fElapsedTime ) const
{
return m_SongTiming.GetBeatFromElapsedTime( fElapsedTime );
}
float StepsGetBeatFromElapsedTime( float fElapsedTime, const Steps &steps ) const
{
return steps.m_Timing.GetBeatFromElapsedTime( fElapsedTime );
}
float SongGetElapsedTimeFromBeat( float fBeat ) const
{
return m_SongTiming.GetElapsedTimeFromBeat( fBeat );
}
float StepsGetElapsedTimeFromBeat( float fBeat, const Steps &steps ) const
{
return steps.m_Timing.GetElapsedTimeFromBeat( fBeat );
}
*/
/* [splittiming]
float GetBeatFromElapsedTime( float fElapsedTime ) const
{
return m_Timing.GetBeatFromElapsedTime( fElapsedTime );
}
float GetElapsedTimeFromBeat( float fBeat ) const { return m_Timing.GetElapsedTimeFromBeat( fBeat ); }
*/
bool HasSignificantBpmChangesOrStops() const;
float GetStepsSeconds() const;
bool IsLong() const;
bool IsMarathon() const;
bool SongCompleteForStyle( const Style *st ) const;
bool HasStepsType( StepsType st ) const;
bool HasStepsTypeAndDifficulty( StepsType st, Difficulty dc ) const;
const vector<Steps*>& GetAllSteps() const { return m_vpSteps; }
const vector<Steps*>& GetStepsByStepsType( StepsType st ) const { return m_vpStepsByType[st]; }
bool IsEasy( StepsType st ) const;
bool IsTutorial() const;
bool HasEdits( StepsType st ) const;
void SetEnabled( bool b ) { m_bEnabled = b; }
bool GetEnabled() const { return m_bEnabled; }
/**
* @brief Determine if the song should be shown on the MusicWheel normally.
* Songs that are not displayed normally may still be available during
* random selection, extra stages, or other special conditions.
* @return true if displayed normally, false otherwise. */
bool NormallyDisplayed() const;
bool ShowInDemonstrationAndRanking() const;
/**
* @brief Add the chosen Steps to the Song.
* We are responsible for deleting the memory pointed to by pSteps!
* @param pSteps the new steps. */
void AddSteps( Steps* pSteps );
void DeleteSteps( const Steps* pSteps, bool bReAutoGen = true );
void FreeAllLoadedFromProfile( ProfileSlot slot = ProfileSlot_Invalid, const set<Steps*> *setInUse = NULL );
bool WasLoadedFromProfile() const { return m_LoadedFromProfile != ProfileSlot_Invalid; }
void GetStepsLoadedFromProfile( ProfileSlot slot, vector<Steps*> &vpStepsOut ) const;
int GetNumStepsLoadedFromProfile( ProfileSlot slot ) const;
bool IsEditAlreadyLoaded( Steps* pSteps ) const;
bool IsStepsUsingDifferentTiming(Steps *pSteps ) const;
/**
* @brief An array of keysound file names (e.g. "beep.wav").
* The index in this array corresponds to the index in TapNote.
* If you change the index in here, you must change all NoteData too.
* Any note that doesn't have a value in the range of this array
* means "this note doesn't have a keysound". */
vector<RString> m_vsKeysoundFile;
CachedObject<Song> m_CachedObject;
RString GetAttackString() const
{
return join(":", this->m_sAttackString);
}
// Lua
void PushSelf( lua_State *L );
private:
/** @brief the Steps that belong to this Song. */
vector<Steps*> m_vpSteps;
/** @brief the Steps of a particular StepsType that belong to this Song. */
vector<Steps*> m_vpStepsByType[NUM_StepsType];
};
#endif
/**
* @file
* @author Chris Danford, Glenn Maynard (c) 2001-2004
* @section LICENSE
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
+2130 -2112
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -810,6 +810,12 @@ cl /Zl /nologo /c verstub.cpp /Fo&quot;$(IntDir)&quot;\
<File
RelativePath="CourseWriterCRS.h">
</File>
<File
RelativePath="CreateZip.cpp">
</File>
<File
RelativePath="CreateZip.h">
</File>
<File
RelativePath="DateTime.cpp">
</File>
+8
View File
@@ -1074,6 +1074,14 @@
RelativePath="CourseWriterCRS.h"
>
</File>
<File
RelativePath="CreateZip.cpp"
>
</File>
<File
RelativePath="CreateZip.h"
>
</File>
<File
RelativePath="DateTime.cpp"
>
+8
View File
@@ -1172,6 +1172,14 @@
RelativePath="ControllerStateDisplay.h"
>
</File>
<File
RelativePath=".\CreateZip.cpp"
>
</File>
<File
RelativePath=".\CreateZip.h"
>
</File>
<File
RelativePath="CryptHelpers.cpp"
>
+2
View File
@@ -455,6 +455,7 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)</Command>
<ClCompile Include="Command.cpp" />
<ClCompile Include="CommonMetrics.cpp" />
<ClCompile Include="ControllerStateDisplay.cpp" />
<ClCompile Include="CreateZip.cpp" />
<ClCompile Include="CryptHelpers.cpp" />
<ClCompile Include="DateTime.cpp" />
<ClCompile Include="Difficulty.cpp" />
@@ -1767,6 +1768,7 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)</Command>
<ClInclude Include="Command.h" />
<ClInclude Include="CommonMetrics.h" />
<ClInclude Include="ControllerStateDisplay.h" />
<ClInclude Include="CreateZip.h" />
<ClInclude Include="CryptHelpers.h" />
<ClInclude Include="DateTime.h" />
<ClInclude Include="Difficulty.h" />
+6
View File
@@ -375,6 +375,9 @@
<ClCompile Include="ControllerStateDisplay.cpp">
<Filter>Data Structures</Filter>
</ClCompile>
<ClCompile Include="CreateZip.cpp">
<Filter>Data Structures</Filter>
</ClCompile>
<ClCompile Include="CryptHelpers.cpp">
<Filter>Data Structures</Filter>
</ClCompile>
@@ -1871,6 +1874,9 @@
<ClInclude Include="ControllerStateDisplay.h">
<Filter>Data Structures</Filter>
</ClInclude>
<ClInclude Include="CreateZip.h">
<Filter>Data Structures</Filter>
</ClInclude>
<ClInclude Include="CryptHelpers.h">
<Filter>Data Structures</Filter>
</ClInclude>
+2
View File
@@ -467,6 +467,7 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)</Command>
<ClCompile Include="Command.cpp" />
<ClCompile Include="CommonMetrics.cpp" />
<ClCompile Include="ControllerStateDisplay.cpp" />
<ClCompile Include="CreateZip.cpp" />
<ClCompile Include="CryptHelpers.cpp" />
<ClCompile Include="DateTime.cpp" />
<ClCompile Include="Difficulty.cpp" />
@@ -1779,6 +1780,7 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)</Command>
<ClInclude Include="Command.h" />
<ClInclude Include="CommonMetrics.h" />
<ClInclude Include="ControllerStateDisplay.h" />
<ClInclude Include="CreateZip.h" />
<ClInclude Include="CryptHelpers.h" />
<ClInclude Include="DateTime.h" />
<ClInclude Include="Difficulty.h" />
+6
View File
@@ -375,6 +375,9 @@
<ClCompile Include="ControllerStateDisplay.cpp">
<Filter>Data Structures</Filter>
</ClCompile>
<ClCompile Include="CreateZip.cpp">
<Filter>Data Structures</Filter>
</ClCompile>
<ClCompile Include="CryptHelpers.cpp">
<Filter>Data Structures</Filter>
</ClCompile>
@@ -1871,6 +1874,9 @@
<ClInclude Include="ControllerStateDisplay.h">
<Filter>Data Structures</Filter>
</ClInclude>
<ClInclude Include="CreateZip.h">
<Filter>Data Structures</Filter>
</ClInclude>
<ClInclude Include="CryptHelpers.h">
<Filter>Data Structures</Filter>
</ClInclude>