From 11f670a303f574dabdb12c919ddeaafa2f07bc26 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Thu, 21 Jun 2012 21:05:59 -0500 Subject: [PATCH] added GetPlayerName(pn) Lua binding to PROFILEMAN --- Docs/Changelog_sm5.txt | 2204 ++++++++++++++++++++-------------------- src/ProfileManager.cpp | 1778 ++++++++++++++++---------------- 2 files changed, 1994 insertions(+), 1988 deletions(-) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index d6a84afcf1..763e34f4a9 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -1,1100 +1,1104 @@ -StepMania 5 Changelog -________________________________________________________________________________ -The StepMania 5 Changelog covers all post-sm-ssc changes. For a list of changes -from StepMania 4 alpha 5 to sm-ssc v1.2.5, see Changelog_sm-ssc.txt. -________________________________________________________________________________ - -================================================================================ -StepMania 5.0 ???? ?? | 20120??? --------------------------------------------------------------------------------- - -2012/06/05 ----------- -* [GrooveRadar] Added SetFromValues(pn,{f1,f2,f3,f4,f5}) Lua binding. [AJ] - -2012/06/02 ----------- -* [PrefsManager] Added StretchBackgrounds preference. [AJ] -* [BMSLoader] Add #banner support. [hanubeki] - Source: http://code.google.com/r/hanubeki-modified-sm-ssc/source/detail?r=bf8b57b9a662af59de66b9d06ca282f38f9126d9 - -2012/05/31 ----------- -* [PaneDisplay] Added NullCountString metric. [AJ] -* [PlayerOptions] Fixes to Get/Set[C, M, X]Mod Lua bindings. [hanubeki] - Source: http://code.google.com/r/hanubeki-modified-sm-ssc/source/detail?r=97761b5dc87b8c8a1b296985a09814337578c745 - -2012/05/27 ----------- -* [MusicWheel] Added EmptyColor metric. [AJ] -* [PlayerState] Enabled GetPlayerController Lua binding. - -2012/05/21 ----------- -* [NotesLoaderBMS] Support for #BMP based background changes. [theDtTvB] -* [SongManager] Add song to the list of songs before loading it, this fixes - crashes in some BMS files. [theDtTvB] -* [ScreenEdit] Allow a new way of creating and modifying attacks using the - Area Menu. Note: Using the C or V keys is no longer allowed for attacks. - It will simplify things for later. [Wolfman2000] -* [Steps] Modified HasSignificantTimingChanges; the following now disqualify - when using a CMod: Stops, Delays, Warps, Speed Changes, Scroll Changes. - Songs with a non-constant BPM will only disqualify if the High/Low difference - is greater than 3.00. [AJ] - -2012/05/19 ----------- -* [Actor] Made the xy command a source-code level command. - -2012/05/17 ----------- -* [LoadingWindow_Gtk] Actually resolve the path to the Splash file. [djpohly] - -2012/05/16 ----------- -* [ScreenWithMenuElements] Added DelayMusicSeconds metric. [AJ] -* [ScreenOptionsMasterPrefs] Allow for FastLoadAdditionalSongs preference - to be called via the "conf" command. [AJ] - -2012/05/14 ----------- -* [Course] Added AllSongsAreFixed() Lua binding. [AJ] - -================================================================================ -StepMania 5.0 alpha 2 | 20120504 --------------------------------------------------------------------------------- - -2012/05/03 ----------- -* Add Var "Player" and Var "Controller" for NoteSkin. [hanubeki] - Sourced from http://code.google.com/r/hanubeki-modified-sm-ssc/source/detail?r=824cff29912d1c29a667046ba463d195e81c524a -* [CustomSpeedMods] If a player decides to remove 1x from the machine profile's - custom speed mods, re-add it back in to avoid crashes. [AJ] - -2012/05/02 ----------- -* Make ReceptorArrowRow and GhostArrowRow respect the column draw order. [hanubeki] - Sourced from http://code.google.com/r/hanubeki-modified-sm-ssc/source/detail?r=8ccf7449651eef51e8c42d031aa64da49a0b72ce - -2012/04/25 ----------- -* [Profile] Added GetLastPlayedSong and GetLastPlayedCourse Lua bindings. [AJ] - -2012/04/22 ----------- -* [LifeMeterBar] Reverted a change from 2010 that messed with how the life meter - subtracts life. The life difficulty should match StepMania 3.9 again. [AJ] - -2012/04/08 ----------- -* [ScreenNetworkOptions] Fixed a bug where localized text would not show up - properly. Fixes issue 759. [AJ] -* [Steps, Song] Replace Steps:UsesSplitTiming with - Song:IsStepsUsingDifferentTiming for both C++ and Lua. [wolfman2000] - -2012/04/06 ----------- -* Modify Jousway's planned noteskin to allow it to work with Technomotion - style gameplay. Expect minor bugs. [Jousway, Wolfman2000] - -2012/04/03 ----------- -* [PlayerOptions] Fix setting some effect mods that were always set to Drunk. - I wonder who had too much to drink. [TaroNuke] - -2012/03/31 ----------- -* [GameManager] Allow beat single7 and versus7 to be shown in Demonstration. [AJ] - -2012/03/28 ----------- -* [ScoreKeeperRave] Actually handle hold scores in HandleHoldScore(). - Players should please provide feedback on how this affects gameplay, as this - is a temporary feature. [AJ] -* [GameConstantsAndTypes] Made StageResult Lua-aware. [AJ] -* [GameState] Added GetStageResult(pn) Lua binding. [AJ] -* [Player] Keysounds now respect the volume settings. [hanubeki] - Sourced from hanubeki-modified-sm-ssc rev. 16fc5b714582 - -2012/03/27 ----------- -* [ScreenEditMenu] Don't hardcode stopping the music on pressing the back button. - This interferes with the StopMusicOnBack metric. [AJ] - -2012/03/20 ----------- -* [Background] Fix 3D noteskins and dancing characters from clashing with each other. [shakesoda, AJ] -* [NoteField] Fix 3D noteskins overlapping. [shakesoda, AJ] -* [ScreenEdit] Don't use Step timing by default. [Midiman] -* [ScreenEdit] Allow playback of course modifiers in Course Edit mode [Midiman] - -2012/03/15 ----------- -* [04 Scoring.lua] Added various 3.9 and 3.9+ scoring methods. [hanubeki] - -2012/03/12 ----------- -* Remove libtheora support since ffmpeg already supports theora videos. [cvpcs] - -2012/03/10 ----------- -* Update ffmpeg support to v0.10. [cvpcs] - -2012/03/09 ----------- -* [PlayerOptions] Don't display x-mods when using m-mods. - Sourced from hanubeki-modified-sm-ssc rev. bd08a58dd7cf and OpenITG. - -2012/03/08 ----------- -* [MusicWheel] Added RouletteStopped message, which is broadcast when Roulette - is finished and the wheel is locked. [AJ] -* [WheelBase] Made WheelState a Lua-enabled enum and added - GetWheelState() Lua binding. Deprecated IsLocked() Lua binding. [AJ] - -2012/03/07 ----------- -* [ScreenSelectMaster] Now updates choices on player join; it will move the - scroller to the correct location, but the GainFocus/LoseFocus commands don't - seem to work. [AJ] - -2012/03/05 ----------- -* [GameCommand] Added GetDifficulty(), GetCourseDifficulty(), GetPlayMode(), - GetSortOrder(), GetAnnouncer(), GetPreferredModifiers(), and - GetStageModifiers() Lua bindings. [AJ] - -2012/03/04 ----------- -* [Player] Changed default Hold window to 0.250f, like it was in 3.9. [AJ] - -2012/03/02 ----------- -* [NotesLoaderBMS] Fix calculating stops, Support for #LNOBJ, Don't use #BACKBMP - as song background if main StepsType is beat-*. [hanubeki] - These changes constitute revisions f26caccf103e, 2d114b38c6c9, and b60f021d2b67 - of hanubeki-modified-sm-ssc. (http://code.google.com/r/hanubeki-modified-sm-ssc/) - -2012/03/01 ----------- -* [MemoryCardManager] Disable Memory Cards by default. If you want to use them, -set MemoryCards=1 in Save/Preferences.ini (or Save/Static.ini). [AJ] -* [GameState] Set Premium to Premium_DoubleFor1Credit by default. [AJ] -* [ScreenSelectMusic] Added PlaySoundOnEnteringOptionsMenu metric. [AJ] -* [MusicWheel, WheelBase] Added collapse sound. [AJ] - -================================================================================ -StepMania 5.0 alpha 1a | 20120219 --------------------------------------------------------------------------------- - -2012/02/19 ----------- -* [Style] Added LockedDifficulty() Lua binding. [AJ] - -2012/02/15 ----------- -* [HighScore] Added Max Combo, Stage Award and Peak Award. New Lua bindings for - HighScore: GetMaxCombo(), GetStageAward(), GetPeakComboAward(). [AJ] - (the specifics of this are subject to change.) - -2012/02/10 ----------- -* [WheelBase, WheelItemBase] Turned WheelItemDataType into a Lua type, - made WheelBase:GetSelectedType() return the enum instead of a number. [AJ] - -2012/02/08 ----------- -* [ScreenEdit] Added support for editing keysounds. Use the Area Menu (Enter) - to either modify what sounds play on that row, or even remove a sound from - the list. Any sounds assigned to empty notes will automatically become - an AutoKeysound, and any AutoKeysounds that have their sound removed will - become empty notes. [Wolfman2000] - -2012/02/08 ----------- -* [ScreenOptionsMaster] Added StepsRowLayoutType metric. - (Valid values are "ShowAllInRow" or "ShowOneInRow".) [AJ] - -2012/01/23 ----------- -* [Player] Tap Note Scores (tns) can now be "AvoidMine" or "HitMine" in -JudgmentMessageCommand. [Saturn2888, shakesoda] - -2012/01/15 ----------- -* [WheelNotifyIcon] Add the NumIconsToShow metric. [Wolfman2000] -* [PlayerOptions] Fix a problem with m-mods where you would get m200 as - the default speed modifier. [AJ] - -2012/01/11 ----------- -* [ScreenEdit] Fix a floating point issue when dealing with speed segments. - [Wolfman2000] - -2012/01/09 ----------- -* [Song] Fix a bug introduced with "Only read certain tags during first load" - where song graphic files wouldn't load. [theDtTvB] - -================================================================================ -StepMania 5.0 alpha 1 | 20120108 --------------------------------------------------------------------------------- - -2012/01/08 ----------- -* [Song] Add HasPreviewVid and GetPreviewVidPath lua binding [cerbo] - -2012/01/08 ----------- -* [ScreenManager] Made AddScreenToTop take a second (optional) parameter for - posting a ScreenMessage on screen pop. [AJ] -* Only read certain tags during first load; makes song loading faster. [theDtTvB] - -2012/01/07 ----------- -* Fix Portable.ini not working on Mac OS X. [shakesoda] - -2012/01/05 ----------- -* [PercentageDisplay] Remove unused ApplyScoreDisplayOptions metric; - added PercentFormat and RemainderFormat metrics. [AJ] -* Fix Portable.ini not working in Linux. [FSX] - -2012/01/04 ----------- -* Fix a scoring/grading bug with Lifts. [FSX] - -2011/12/27 ----------- -* [MusicWheel] Add IsRouletting Lua binding. [AJ] -* [LuaManager] Remove GetOSName Lua binding; use GetArchName instead. [AJ] - -2011/12/26 ----------- -* [ArchHooks_OSX] Worked around a crash when language detection goes wrong. - Note: a real fix should be looked into. [shakesoda] - -2011/12/23 ----------- -* [Song] Fixed a bug where a sample start of 0 wouldn't work. [AJ] -* [Game] Added CountNotesSeparately and GetMapJudgmentTo(TapNoteScore) - Lua bindings. [AJ] -* [StepMania.cpp] Fix initial aspect ratio on first boot, hopefully. - (See issues 6 and 27) [AJ] - -2011/12/22 ----------- -* [LuaManager] Added ProductFamily() Lua binding. [AJ] - -2011/12/17 ----------- -* [Various] Allow loading of *.jpeg in addition to *.jpg. [AJ] - -2011/12/16 ----------- -* [StreamDisplay] Added VelocityMultiplier, VelocityMin, VelocityMax, - SpringMultiplier and ViscosityMultiplier metrics. [AJ] - -2011/12/12 ----------- -* [ScreenEdit] Add the GAMESTATE:InStepEditor Lua binding. [Wolfman2000] -* [Player, ScreenGameplay] Allow failing on Oni without crashing. This one - took awhile. [Wolfman2000] -* [LifeMeterBattery] Fixed various issues (lives not fully disappearing on fail, - P2 lose life animation having the wrong x zoom, hide the lives number if it - falls below 0). [AJ] - -2011/12/11 ----------- -* [ScreenEdit] Restore cycling the timing segments for jumping between. - The required line somehow never got replaced. [Wolfman2000] - -2011/11/30 ----------- -* [PlayerOptions] Added IsEasierForSongAndSteps(Song,Steps,PlayerNumber) and - IsEasierForCourseAndTrail(Course, Trail) Lua bindings. [AJ] -* [PlayerState] Added GetSuperMeterLevel() Lua binding. [AJ] - -2011/11/28 ----------- -* [ScreenGameplay] Add the SurvivalModOverride metric. Let the themer decide - if mods should be overridden on survival or not. Funny enough, this used - to be true for the old Oni style mode, but...well, we'll cross that bridge - later. [Wolfman2000] -* [LifeMeterBattery] Added MaxLives metric, which limits the maximum amount of - lives. Setting this to 0 will remove the limit. [AJ] - -2011/11/27 ----------- -* [PlayerOptions] Pretty large changes here, namely a bunch of new bindings. - Fixed the logic for GetReversePercentForColumn; It will now return nil for - invalid columns. Also fixed the logic for UsingReverse (now checks for 1.0f) - and SetPassmark (no longer allows values < 0.00f and > 1.0f). [AJ] -* [ScreenEdit] Allow inserting and removing beats and timing changes in - specific note increments instead of just quarter notes (a whole beat). - Those that prefer to keep using the shortcut keys will note that the - behavior has not changed for that: only by going into the Area menu can you - deal with more specific changes. [Wolfman2000] - -2011/11/26 ----------- -* [ScreenEdit] Restore using F9 and F10 to adjust stops by a fixed amount. - Sorry for the delay in this. [Wolfman2000] -* [ScreenEdit] Minor convenience. If you attempt to create a negative stop - segment from scratch, it does not create, and you are not requested to - save on exit, for there is nothing to save. [Wolfman2000] -* [ScreenEdit] Allow Shift + F9/F10 for adjusting delays. This works the same - way as adjusting stops. [Wolfman2000] - -2011/11/25 ----------- -* [PlayerStageStats] Hitting a mine no longer gives you full combo when - [Gameplay] MineHitIncrementsMissCombo=true. [AJ] - -2011/11/24 ----------- -* [PlayerStageStats] Added GetFailed and GetNumControllerSteps Lua bindings. [AJ] - -2011/11/15 ----------- -* [LifeMeterBar] Added the ForceLifeDifficultyOnExtraStage metric and - the ExtraStageLifeDifficulty metric. Let the themer decide if extra stages - should have their own life bar behavior. Note that this metric does NOT - change the lifebar to the battery style. [Wolfman2000/FSX] - -2011/11/14 ----------- -* [Mac OS X] Restore JPEG functionality. [Wolfman2000] - -2011/11/06 ----------- -* [GameState] Add the RefreshNoteSkinData lua binding. This will only - refresh the NS data for the present game, not all games. [Wolfman2000] -* [ScreenSelectMusic] Fixed Rave difficulties not being synced on late join. - Fixes issue 577. [AJ] -* [GameplayAssist] Don't play sounds if the player is dead. Fixes issue 621. [AJ] - -2011/11/04 ----------- -* [ScoreKeeperRave] Revert fix from 2011/10/28. [AJ] -* [ScoreKeeperRave] Fixed Miss and HitMine giving meter life. - (Fixes issue 622.) [AJ] - -2011/11/02 ----------- -* [ArchHooks] Add the GetArchName lua binding. To the themers that use - GetOSName, that function may be deprecated in the future. For now, - both options exist. [vyhd, Wolfman2000] - -2011/11/01 ----------- -* [ArrowEffects] Fix Expand, and possibly other mods, from breaking if - using a second player. [Wolfman2000] -* [ArchHooks] Add the AppHasFocus lua binding. [vyhd, Wolfman2000] - -2011/10/29 ----------- -* [GameState] Add the ResetPlayerOptions lua binding. [Wolfman2000] - -2011/10/28 ----------- -* [ScoreKeeperRave] Fix an issue where the super meter would not decrease back - to 1 after hitting the end of 3. (Fixes issue 314.) [AJ] - -2011/10/27 ----------- -* [Default theme] Fixed the pref controlling timing segments on song meter. [FSX] - -2011/10/18 ----------- -* [LightsManager] Use song beat for menu button lights, allow demonstration to - flash pad lights when BlinkGameplayButtonLightsOnNote is true, light custom - game buttons when pressed during attract mode, general optimizations. [vyhd] - -2011/10/17 ----------- -* [ScreenEdit/NoteField] Fix an editor crash when you exit without saving - after creating new steps. [Wolfman2000] - -2011/10/16 ----------- -* [NoteDataUtil] Add the Backwards mod for games where the intended - definition of Mirror is different. Regarding Pump gameplay, what was - called Mirror in Preview 4 is considered Backwards now, and the original - Mirror is back in its old position. [Wolfman2000] - -2011/10/12 ----------- -* [Steps] Fix a bug where e.g. ".SM" ".DWI" ".Sm" ".sM" files - wouldn't properly load since the code was expecting lowercase. [AJ] - -2011/10/10 ----------- -* [NotesLoaderBMS] Add the time signature segments. [theDtTvB] - -2011/10/09 ----------- -* [NotesLoaderBMS] Fix the bug where keysounds that points to nonexistant file - gets assigned a random one. [theDtTvB] -* [NotesLoaderBMS] Use BMSLoader to load PMS files. [theDtTvB] -* [RageSoundReader_WAV] Fix ADPCM support. [theDtTvB] - -2011/10/08 ----------- -* [GameSoundManager] Add the PlayMusicPart lua binding. [Wolfman2000] -* [ScreenEdit] Add the FadeInPreview and FadeOutPreview metrics. This controls - how long the fade in and fade outs are for playing the preview music. - The default values are 0 and 1.5 respectively. [Wolfman2000] - -2011/10/07 ----------- -* [RageDisplay] Add the GetFPS, GetVPF, and GetCumFPS bindings. [Wolfman2000] - -2011/10/06 ----------- -* Various scoring fixes sourced from http://www47.atwiki.jp/waiei/pages/21.html - [A.C/@waiei, 桜為小鳩/@sakuraponila] - -================================================================================ -StepMania 5.0 Preview 4 | 20111005 --------------------------------------------------------------------------------- - -2011/10/04 ----------- -* [NoteDataUtil] More accurate Left, Right, and Mirror mods for Pump gameplay. - Major thanks to Hudson Felker and Bill Shillito here. [Wolfman2000] - -2011/10/01 ----------- -* [ScreenHighScores] Disable forced screen transition behavior when - ManualScrolling=true. [AJ] - -2011/09/30 ----------- -* [GameState] Added CurrentOptionsDisqualifyPlayer(player), - ApplyPreferredModifiers(player,string) and ApplyStageModifiers(player,string) - Lua bindings. [AJ] - -2011/09/29 ----------- -* [Fallback theme] Fix ImmediateHoldLetGo function. [Wolfman2000] -* [GameState] Add the EditAllowedForExtra metric. Use this if you want edit - steps to be allowed for accessing the extra stage. By default, this is - false. [Wolfman2000] - -2011/09/26 ----------- -* [Default theme] Added Song Timing Display user preference. [AJ] -* [ThemeManager] Add global Scripts dir. [shakesoda] - -2011/09/25 ----------- -* [WheelItemBase] Added GetColor and GetText Lua bindings. [AJ] - -2011/09/24 ----------- -* [ScreenEdit] Disable shifting timing changes down one beat if starting on - beat 0. Important information must stay on that beat. [Wolfman2000] -* [ScreenEdit] Disable converting rows to a stop or beat starting on beat 0. - There should be no reason for this at this time. [Wolfman2000] -* [MusicWheelItem] Add/reinstate MusicWheelItem Mode Normal/Color/OverPart. [AJ] -* [FadingBanner] Added LoadFromSortOrder(SortOrder) Lua binding. [AJ] - -2011/09/23 ----------- -* [ScreenEvaluation] Added RollingNumbersMaxComboClass metric. [AJ] -* [NotesLoaderSM] Fix loading .sm files with non standard difficulty names. - It should be Hard, not Heavy. [Wolfman2000] - -2011/09/22 ----------- -* [ScreenDebugOverlay] Replaced hardcoded toggle command with - ButtonTextToggledCommand metric. [AJ] -* [LoadingWindow_Win32] Make the StepMania window gain focus after the - loading window closes. Fixes issue 424. [AJ] - -2011/09/21 ----------- -* [FadingBanner] Added LoadRandom(), LoadRoulette(), LoadFallback(), - LoadCourseFallback(), and GetBanner(int) Lua bindings. [AJ] - -2011/09/18 ----------- -* [Song] Added GetSampleStart() and GetSampleLength() Lua bindings. [Wolfman2000] - -2011/09/16 ----------- -* [UnlockManager] Added GetNumLockedSongs() Lua binding. [Wolfman2000] -* [UnlockManager] Added IsSongLocked() Lua binding. [Wolfman2000] - -2011/09/12 ----------- -* [NotesLoaderSSC/WriterSSC] Allow all timing tags regardless of what timing - is used. [Wolfman2000] - -2011/09/11 ----------- -* [ScreenEvaluation] Added "evaluation full combo W1" and - "evaluation full combo W2" announcer cues. [AJ] -* [Banner] Added "Banner group fallback" graphic. [AJ] - -2011/09/09 ----------- -* [NotesLoaderBMS] Rewrite the BMS loader, should fix issues 430 and 500. [theDtTvB] - -2011/09/08 ----------- -* [GameManager] Fix shifting of 2P notes in beat mode. [1a2a3a2a1a] - -2011/09/07 ----------- -* [Model] Added GetDefaultAnimation() Lua binding. [AJ] -* [GameState] Added GetEarnedExtraStage() Lua binding. [AJ] - -2011/09/02 ----------- -* [MenuTimer] Added start(), disable() Lua bindings. Also renamed setseconds to - SetSeconds to match GetSeconds. [AJ] -* [GameManager] beat "versus" -> "versus5"; fix beat versus7 being "single7". [1a2a3a2a1a] - -2011/08/27 ----------- -* Updated libjpeg to 8c. -* [SongManager] Added GetCoursesInGroup(sCourseGroup,bIncludeAutogen), - GetSongGroupBannerPath(songGroup), GetCourseGroupBannerPath(courseGroup), - DoesSongGroupExist(songGroup), DoesCourseGroupExist(courseGroup) and - GetPopularSongs() Lua bindings. [AJ] -* [SongManager] Added GetPreferredSortSongs(), GetPreferredSortCourses(courseType,bIncludeAutogen), - and GetPopularCourses(courseType) Lua bindings. [AJ] -* [SongManager] Add SongToPreferredSortSectionName(song), WasLoadedFromAdditionalSongs(song), - and WasLoadedFromAdditionalCourses(course) Lua bindings. [AJ] -* [CryptManager] Add GenerateRandomUUID() Lua binding. [AJ] -* [ThemeManager] Added DoesThemeExist(sTheme), IsThemeSelectable(sTheme), - DoesLanguageExist(sLang), GetCurThemeName(), HasMetric(sGroup,sValue), and - HasString(sGroup,sValue) Lua bindings. [AJ] - -2011/08/23 ----------- -* [Makefile.am] Fixed version date and time handling. [AJ] - -2011/08/22 ----------- -* [PrefsManager, X11Helper] Added ShowMouseCursor preference. [AJ] -* [UnlockManager] Added GetStepOfAllTypes Lua binding. This gets the locked - Steps for all game types based on the difficulty specified. [Wolfman2000] -* [UnlockManager] Added requirepasschallengesteps Lua binding. This is more - self-explanitory: pass challenge to be able to play edits. [Wolfman2000] - -2011/08/21 ----------- -* [NotesLoaderSSC] Fix loading pre-split timing files that had blank timing - tags inside of them. Thanks to Vin.il for the catch. [Wolfman2000] -* [Song] Added Jacket, CD image (a la early DDR), and Disc (PIU-style) support. - Added GetJacketPath(), GetCDImagePath(), GetDiscPath(), HasJacket(), HasDisc(), - and HasCDImage() Lua bindings. [AJ] - -================================================================================ -StepMania 5.0 Preview 3 | 20110820 --------------------------------------------------------------------------------- - -2011/08/20 ----------- -* [PlayerOptions] Add GetMMod() Lua binding. [AJ] -* [Player] Make keysounds respect volume preference. Fixes issue 344. [AJ] - -2011/08/19 ----------- -* [Steps] Add PredictMeter() and GetDisplayBPMType() Lua bindings. [AJ] -* [Song] Add ShowInDemonstrationAndRanking() Lua binding. [AJ] -* Turn off Autogen by default. [shakesoda] -* Disable automatic aspect ratio guessing, default to 854x480 - (16:9 because most newer displays are wide). [shakesoda] -* Turn on FastLoad and FastLoadAdditionalSongs by default. [shakesoda] - -2011/08/18 ----------- -* [RageInput] Added "No input devices were loaded." string to languages. [AJ] -* [RageInputDevice] Added localized names for InputDeviceState. [AJ] -* [Course] Add IsPlayableIn(StepsType) and IsRanking() Lua bindings. [AJ] -* [Trail] Added GetTotalMeter(), GetLengthSeconds(), IsSecret() - and ContainsSong(song) Lua bindings. [AJ] - -2011/08/16 ----------- -* Added PrettyPercent(numerator,denominator) Lua binding. [AJ] - -2011/08/14 ----------- -* [Foreground] Restore Foreground Changes for use in gameplay. Note that it - is recommended to use lua for #FGCHANGES from now on: not all XML changes - will work. [infamouspat] - -2011/08/13 ----------- -* [Theme-side] Added Fancy UI Background preference to Theme Options. [AJ] -* [LowLevelWindow_X11] Don't force the window into the upper left corner. [ZipFile] - -2011/08/07 ----------- -* [LifeMeterBattery] Added LostLife param to LifeChanged message. [AJ] -* [LifeMeterBattery] Converted LifeMeterBattery lives to an AutoActor. [AJ] -* [TimingData] Add HasDelays() Lua binding; HasStops() now only checks stops. [AJ] -* [GameState, SongUtil] Fix Issue 263 by not charging 2x stages for doubles when - not using joint premium. [AJ] -* [BeginnerHelper] Made BeginnerHelper run the OnCommand. [AJ] -* [GameState] add GetExpandedSectionName() Lua binding. [AJ] -* [ScreenSelectMusic] Added IdleCommentSeconds metric and - "ScreenSelectMusic IdleComment" announcer sound. [AJ] -* [NotesLoaderBMS] "Send the actual song file to LoadFromBMSFile in - BMSLoader::LoadNoteDataFromSimfile instead of the dummy one... - This fixes the wrong sound issue [423]..." [theDtTvB] - -2011/08/06 ----------- -* [NoteSkins/beat/default] Fix Issue 425. [AJ] -* [ScoreDisplayRave] Allow (Meter/Level)(X/Y) metrics to work again. [AJ] - -2011/08/05 ----------- -* [NoteField] Added AreaHighlightColor metric. [AJ] - -2011/08/04 ----------- -* [NoteTypes, ScreenEdit] Removed artificial MAX_NOTES_PER_MEASURE limit. [AJ] - -2011/08/02 ----------- -* [NotesSSC] Only write timing/attack tags for the step if there is a - difference from the song. For timing tags, at this time it means that if even - one tag is different, all tags are written. [Wolfman2000] - -2011/08/01 ----------- -* [MusicWheel, RoomWheel] Moved the "- EMPTY -" string to the languages file. [AJ] - -2011/07/31 ----------- -* [ScreenGameplay, LyricDisplay] Stop lyrics from animating on failure. - Fixes issue 298. [AJ] - -2011/07/30 ----------- -* [ProfileManager] Fix an issue when deleting recently created profiles. [AJ] -* Start removing anything related to Guitar mode. This was rushed in, and it - is not worth us keeping at this time. [Wolfman2000] - -2011/07/26 ----------- -* [ScreenEdit] Add a semi working implementation of the often requested - copy/paste selected timing data feature. This should make it easier for - some charters. [Wolfman2000] - -2011/07/21 ----------- -* [BeginnerHelper] Removed DancePadAngle metric in favor of DancePadOnCommand. - The same goes for PlayerAngle, dancer rotation is now handled in - PlayerP1/2OnCommand. [AJ] -* [Course] Bumped up max edit course title length to 16 (still feels too short). - Also added #DESCRIPTION tag and Course:GetDescription() Lua binding. [AJ] - -2011/07/20 ----------- -* [Win32/CrashHandlerChild] Crashlog and log now open in the player's default - text editor. Also, the Show Log button works again, including for people using - Portable.ini. [AJ] - -2011/07/19 ----------- -* [LoadingWindow] Added the ability for themes to have custom splash banners. - (Currently Windows-only.) [AJ] - -2011/07/17 ----------- -* [Cache] No longer store #NOTES in the cache. This should speed things up - on the first load if there is not much to write. (General note: this was - taken from another branch, but results at that point were great.) - [Wolfman2000] - -2011/07/13 ----------- -* [Difficulty] Allow ALL StepsTypes to use CustomDifficulty properly. - There was some unfair targeting of Couple and Routine. [Wolfman2000] -* [Steps] Calculate accurate radar values for Couple charts. [Wolfman2000] -* [ScreenEdit] Display more accurate chart data for Couple and Routine charts - for the future. No more having (almost) every row as a jump! [Wolfman2000] - -2011/07/12 ----------- -* [OptionRowHandler] Add a new metric to ScreenOptionsMaster: - StepsUseChartName. Use this if you want your charts to have a unique name - in the options menu. If there is no #CHARTNAME or it is "Blank", it reverts - to the original behavior. This metric is false by default. [Wolfman2000] -* [ScreenEdit] Fixed a bug involving #ATTACKS. Now when you set an attack, - the mods are reverted back to how they were prior to the attack being set. - [Wolfman2000] - -2011/07/09 ----------- -* [NotesTheUsual] Update the #COMBOS tag to allow for a Miss Combo attribute. - Any files that only use the Combo attribute will have that value copied to - miss combo on next launch. [Wolfman2000] -* [ScoreKeeperNormal] Better match #COMBOS with eval. Scoring formulas should - not be affected, but it may require more testing. [Wolfman2000] -* [Metrics] Have Pump mode lump the checkpoint judgments with Flawless and - Miss judgments on eval. Of course, this goes down to Perfect and Miss if - that is disabled. [Wolfman2000] - -2011/07/07 ----------- -* [ScreenEdit] Fix the NoMines transformation bug, issue 363. [Wolfman2000] -* [CourseLoaderCRS] Don't load BEST# and WORST# where # is greater than the - number of songs installed. Fixes issue 373. [AJ] -* [NotesAllSSC] Add the #CHARTNAME tag to the Steps. #DESCRIPTION is now for - more detailed descriptions, or perhaps some short hand lingo. All files - that used #DESCRIPTION will have their values moved to #CHARTNAME on - load. [Wolfman2000] -* [ScreenEdit] Add a Steps Data menu for getting numerical step data on the - chart. This is a read only menu. Edit Steps Information contains writable - information. [Wolfman2000] -* [NotesAllSSC] Add the Steps version of #DISPLAYBPM. The Song version is - still there, so themes should not have to worry about breakage. - [Wolfman2000] - -2011/07/06 ----------- -* [ScreenEdit] Fix the bug where hitting Enter during playing wouldn't take - the user back to the editor. [Wolfman2000] -* [Gameplay] Fix Fail mods being dishonored. [Midiman] - -2011/07/05 ----------- -* [ScreenEdit] Restore dance-couple and pump-couple for editing purposes. - Saving should still work, but this was never tested yet. [Wolfman2000] -* [ScreenOptions] Mini is now ITG Mini, and Tiny is now Pump Pro Mini. - This will prevent many prior courses from breaking. [sharksoda, Wolfman2000] -* [CharacterManager] Add a lua function to check how many characters you have. - For an example of how this is used, check the default theme's scripts - folder, specifically 03 ThemePrefs.lua. [Wolfman2000] - -2011/07/04 ----------- -* [ScreenEdit] Add a function to switch the notes the routine players have to - hit. In simple terms, Player 1's notes are now Player 2's and vice~versa. - Check it out in the Alter Menu. [Wolfman2000] -* [ScreenEdit] Add two routine mirroring functions. Now you can build sections - of a chart for one player, and mirror the effect for the other player when - finished. For Pump players, it is not a straight mirror, but is more akin - to what is found via normal routine charts. In other words, you'll be happy. - Check it out in the Alter Menu. [Wolfman2000] - -2011/07/03 ----------- -* [ScreenEdit] Fix a crash if one tries to remove an attack that doesn't - exist at that time. [Wolfman2000] - -================================================================================ -StepMania 5.0 Preview 2 | 20110703 --------------------------------------------------------------------------------- - -2011/07/03 ----------- -* [Player] Bring mMods from OpenITG over. Also, a metric was added, - "MModHighCap", to cap the speed mod if required for playing songs like - Tsuhsuixamush. Set the metric to 0 or less to remove the cap. [AJ, sharksoda, - Wolfman2000] - -2011/07/02 ----------- -* [ScreenEdit] Fixed a crash when hitting Enter in the F1 help menu. [AJ] - -2011/06/30 ----------- -* [NotesAll] Use #FIRSTSECOND, #LASTSECOND, and #LASTSECONDHINT instead of the - former BEAT equivalents. Split Timing has made this a necessity thanks to - certain files that abuse Stops/Delays more than usual. [Wolfman2000] -* [ScreenEdit] Add a function in the Area Menu to designate the current beat - as the last second of the song. Please try to be smart and not use this too - early. [Wolfman2000] - -2011/06/28 ----------- -* [ScreenEdit] Add a function to copy/paste the TimingData of a player's - choice. Remember to be in the appropriate mode when copying and pasting. - By default, the song timing is already located in the clipboard, ready for - use. [Wolfman2000] - -2011/06/27 ----------- -* [Steps] Make sure #ATTACKS are copied when requested. [Wolfman2000] -* [ScreenEdit] Have Step Author up front instead of Chart Style. This is - probably going to be better overall. [Wolfman2000] -* [TimingData] Preserve the length of time for Speed Segment scaling when using - beats. [Wolfman2000] -* [NotesLoader/WriterSSC] #OFFSET is to be before #ATTACKS. This is required if - we pursue beat based attacks and not just second based. [Wolfman2000] - -2011/06/26 ----------- -* [UnlockManager] New metric: AutoLockEditSteps. Use this to hide bonus charts - until the Expert steps are beaten. No guarantee that this works with no - challenge steps in the song. This defaults to false. [Wolfman2000] -* [UnlockManager] New metric: SongsNotAdditional. Set to true to keep the - default behavior, false to have the AdditionalSongs folder contain - unlockable material. This is set to true to start. [Wolfman2000] -* [ScreenEdit] Allow jumping between all segments, not just Label segments. - You still use Ctrl + ,/. to jump, but now you use Ctrl + N/M to cycle the - segments. By default, it starts with Label. [Wolfman2000] -* [PlayerOptions] No longer display StepAttacks in the player's list. - Instead, show NoAttacks if attacks are disabled. [Wolfman2000] - -2011/06/24 ----------- -* [Actor] Implement compound(length,tweens) in _fallback/02 Actor.lua. [AJ] -* [UnlockManager] Add a new unlock reward: StepsType. This is similar to - unlocking Steps, but it is targeted for one step in one stepstype rather - than one step in all stepstypes. This needs testing. [Wolfman2000] -* [ScreenEdit] Add the option to convert delays to beats. Just find a better - song to use this on besides Uprock. [Wolfman2000] -* [ScreenEdit] Fix a crash if you don't save any steps on a new song. - [Wolfman2000] -* [NotesLoader/WriterSSC] Add support for Step #ATTACKS. Furthermore, Song - Attacks (or rather, Step Attacks as it should be called now) are turned on - by default instead of off. [Wolfman2000] - -2011/06/19 ----------- -* [EditMenu] Allow all songs to work in Practice Mode, regardless of folder - location. This fixes a crash if everyone had songs in AdditionalSongs. - [Wolfman2000] - -2011/06/17 ----------- -* [LifeMeterBattery] Fixed a bug where MinesSubtractLives was not being honored. - Also added LifeChanged message to changing of life on holds. [AJ] - -2011/06/15 ----------- -* [TimingData] Added many lua bindings for the other timing segments. GetWarps, - GetCombos, GetTimeSignatures, GetTickcounts, GetFakes, GetScrolls, GetSpeeds. - This should cover all of them now. [Wolfman2000] - -2011/06/13 ----------- -* [InputHandler_DirectInput] Fixed MouseWheel input not resetting. [AJ] -* [ScreenTextEntry] Make it so only the keyboard's Enter key can finish the - screen. Should fix issues with buttons whose secondary function is MenuStart. [AJ] -* [InputMapper] Modify default mappings. Use the Hyphen key instead of the - Numlock key for Player 2's GAME_BUTTON_BACK. This should address some - issues with Player 2 being unable to back out if they use a laptop. - [Wolfman2000] -* [NoteDisplay] Add two new metrics. - * DrawRollHeadForTapsOnSameRow: bool, similar to DrawHoldHeadForTapsOnSameRow - * TapHoldRollOnRowMeansHold: bool, true means hold and false means roll - * No noteskins should require updating, as these were placed in common/common - for ease of use. [Wolfman2000] -* [LifeMeterBattery] Added ChangeLives(int) Lua binding. [AJ] -* [LifeMeterBattery] Added DangerThreshold metric. [AJ] -* [LifeMeterBattery] Added some important metrics. [AJ] - * MinScoreToKeepLife='TapNoteScore_*' - any score below this = loss of life. - * SubtractLives=1 - how many lives are lost when going below MinScoreToKeepLife. - * MinesSubtractLives=1 - how many lives are lost when hitting a mine. - * HeldAddLives=0 - how many lives are gained when a hold is completed. - * LetGoSubtractLives=1 - how many lives are lost on a dropped hold. - -2011/06/12 ----------- -* [ScreenNetSelectMusic] Add PlayerOptionsScreen metric. [AJ] -* [ScreenEdit] Restore the old PageUp/PageDown behavior, added Control + - PageUp/PageDown to use recent time signature behavior. Laptop users, that - includes you guys too: semicolon and apostrophe are still good. [Wolfman2000] - -2011/06/11 ----------- -* [ScreenEdit] Allow setting the Music Preview via the Alter Menu. Just select - your area, enter the menu, and choose "Designate as Music Preview". No more - math calculations needed! [Wolfman2000] -* [SongUtil] Added GetPlayableSteps(Song) Lua binding. [AJ] -* [Steps] Allow 255 characters for all chart descriptions, including edits. - We are no longer bound by In The Groove I think. [Wolfman2000] -* [Player] Add GetPlayerTimingData() Lua binding. [Wolfman2000] - -2011/06/10 ----------- -* [ScreenEdit] Split the Area Menu into the Area Menu and Alter Menu. Use the - "A" key to enter the Alter Menu when a selection of notes/rows are - highlighted. Use the Enter key to enter the old Area Menu for the options that - do not depend on selecting NoteData. [Wolfman2000] -* [ScreenEdit] Allow converting selections to Delays, Warps, or Fakes as well - as Stops. Remember, use the Alter Menu for this. [Wolfman2000] - -2011/06/09 ----------- -* [ScreenSyncOverlay] Ensure that F11 / F12 work with all charts due to Split - Timing. [Wolfman2000] - -2011/06/08 ----------- -* Any notes in a fake segment or warp segment are completely ignored for - scoring purposes. Now you can get 100% on your warping goodness! - [Wolfman2000] - -2011/06/06 ----------- -* [PlayerOptions] Removed the ScoreDisplay mod choices. Use lua to make your - own scoring formulas that work in reverse instead. [Wolfman2000] -* [ScreenGameplay] Fix an assist tick bug if there was no Player 1. Note that - this changes the behavior slightly: it is the first enabled player, or - master player, that gets the ticks now. A better solution will be looked at - in the future. [Wolfman2000] -* [NoteDataUtil] Fix a radar issue involving hands. Unfortunately, this means - yet another cache reload for accuracy purposes. [Wolfman2000] - -2011/06/04 ----------- -* Changed default MusicWheelSwitchSpeed to 15 (was 10). [AJ] -* [AnnouncerManager] Fixed a bug where no announcers would be loaded. [AJ] -* Restored the UserPrefAutoSetStyle behavior. [Wolfman2000] -* [NotesLoaderSMA] Better way of identifying beats and seconds. [Wolfman2000] - -================================================================================ -StepMania 5.0 Preview 1a | 20110603 --------------------------------------------------------------------------------- - -2011/06/03 ----------- -* [LifeMeterBattery] Added LivesLeft param to LifeChanged message. [AJ] -* [Windows] Set up directories for pictures and app data in their proper - location. [Henke] -* [NotesLoaderSM] Fix an Offset load bug. [Wolfman2000] - -2011/06/02 ----------- -* [BPMDisplay] Added SetFromSteps Lua binding. [AJ] -* [ScreenDebugOverlay] Switch the R and T keys to be Volume Down and Up - respectively. I have to admit, it makes more sense to have volume up be - on the right instead of the left. [Wolfman2000] -* [SongManager] Make autogen courses have "Autogen" as the Scripter. [AJ] - -2011/06/01 ----------- -* [TimingData] Added the HasScrollChanges lua binding. [Wolfman2000] -* [ScreenEdit] Fix Song Timing behaviors. [Wolfman2000] - -2011/05/31 ----------- -* [Player] Added the BattleRaveMirror metric. This determines if Battle and - Rave mode will have the two players with mirrored charts or not. By default, - this is set to true, preserving the ITG style behavior. [Wolfman2000] -* [TimingData] Added the HasScrollChanges lua binding. [Wolfman2000] - -================================================================================ -StepMania 5.0 Preview 1 | 20110529 --------------------------------------------------------------------------------- - -2011/05/27 ----------- -* [ScreenEdit] Added the LoopOnChartEnd metric. Once you get to the end of - the chart while playing it in the editor, this controls whether it loops and - plays again, or simply stops. By default, this is true, replicating current - behavior. Set to false to replicate older StepMania behavior. [Wolfman2000] - -2011/05/26 ----------- -* [ScoreKeeperNormal] Added the MissComboIsPerRow metric. Similar to the - ComboIsPerRow metric, this determines how much miss combo is earned on missing - a row of notes. By default, this is true. Set to false to replicate Pump Pro - behavior. [Wolfman2000] - -2011/05/25 ----------- -* [NotesLoaderSSC/NotesWriterSSC] Added the ScrollSegments. Think BPM change, - but not. [theDtTvB] - -2011/05/23 ----------- -* [Steps] Added the UsesSplitTiming Lua binding. [Wolfman2000] - -2011/05/20 ----------- -* [CryptManager] Added SHA1File Lua binding. [AJ] - -2011/05/19 ----------- -* [BPMDisplay] Add CourseCycleSpeed metric. [AJ] - -2011/05/17 ----------- -* [NotesWriterSM] Write out OpenITG compatible SM files from here on out. - This includes turning Warps into Negative Stops. For those that wanted - negative BPMs specifically, my apologies, but stops are easier on math. - [Wolfman2000] - -2011/05/16 ----------- -* [ProfileManager] Added ProfileWasLoadedFromMemoryCard(PlayerNumber) - Lua binding. [AJ] -* Added #FAKES to the SSC format. Similar to the fake arrows, these blocks - prevent all judgments within the range. [Wolfman2000] -* Changed the syntax of #WARPS slightly. Now the second value is the relative - distance that is skipped, not the absolute value when you start hitting - arrows again. [Wolfman2000] - -2011/05/15 ----------- -* [ScreenGameplay] Removed hardcoded commands for Debug (give up text) and - replace them with DebugStartOnCommand, DebugBackOnCommand, and - DebugTweenOffCommand. [AJ] -* Added #SPEEDS to the SSC format. This multiplies your scrolling speed during - gameplay, not replaces it (see mod attacks for replacing). [Wolfman2000] - -2011/05/14 ----------- -* [ModIcon] Added StopWords metric. [AJ] -* [ScreenSelectMaster] Add "ScreenEmpty" param to MenuStartP# when the GameCommand - doesn't set a screen. [AJ] -* [StepsDisplay] Added MeterFormatString metric. [AJ] -* [MusicWheel] Added ShowSectionsInBPMSort and ShowSectionsInLengthSort metrics. [AJ] -* [ScreenEvaluation] Stop the Bonus bars from overflowing in course modes. [AJ] -* [Banner] Added ScrollMode and ScrollSortOrder metrics. [AJ] - -2011/05/13 ----------- -* Added Split Timing to .SSC files. All older .SSC files and other file - formats are converted to split timing on cache load. We are no longer bound - by Song Timing for everything. [theDtTvB, Wolfman2000, TeruFSX] - -2011/05/11 ----------- -* [GameSoundManager] Added PlayAnnouncer Lua binding. [AJ] -* [AnnouncerManager] Add support for "gameplay combo #" for announcer. [AJ] - -2011/05/10 ----------- -* [Sprite] Added SetSecondsIntoAnimation Lua binding. [AJ] -* [BPMDisplay] Added SetFromCourse Lua binding. [AJ] - -2011/05/03 ----------- -* [ScreenEdit] Allow changing the Beat 0 Offset, Music Sample Start, and - Music Sample Length via Edit Song Info menu. [Wolfman2000] - -2011/05/02 ----------- -* [ScreenSelectMusic] Added NullScoreString metric. [AJ] - -2011/04/17 --------- -* Use lua for all primary score keeping. Course modes right now still use the - old fashioned system. [TeruFSX, Wolfman2000] - -2011/04/09 --------- -* [Player] Force hold judgments to take place before setting the score. - [theDtTvB] - -2011/04/05 --------- -* [NotesLoaderSSC, NotesWriterSSC] Add the #LABELS tag. This is meant for step - editors to label different parts of their stepcharts. Use Control + , or . to - jump to different labels made. [Wolfman2000] - +StepMania 5 Changelog +________________________________________________________________________________ +The StepMania 5 Changelog covers all post-sm-ssc changes. For a list of changes +from StepMania 4 alpha 5 to sm-ssc v1.2.5, see Changelog_sm-ssc.txt. +________________________________________________________________________________ + +================================================================================ +StepMania 5.0 ???? ?? | 20120??? +-------------------------------------------------------------------------------- + +2012/06/21 +---------- +* [ProfileManager] Added GetPlayerName(pn) Lua binding. [AJ] + +2012/06/05 +---------- +* [GrooveRadar] Added SetFromValues(pn,{f1,f2,f3,f4,f5}) Lua binding. [AJ] + +2012/06/02 +---------- +* [PrefsManager] Added StretchBackgrounds preference. [AJ] +* [BMSLoader] Add #banner support. [hanubeki] + Source: http://code.google.com/r/hanubeki-modified-sm-ssc/source/detail?r=bf8b57b9a662af59de66b9d06ca282f38f9126d9 + +2012/05/31 +---------- +* [PaneDisplay] Added NullCountString metric. [AJ] +* [PlayerOptions] Fixes to Get/Set[C, M, X]Mod Lua bindings. [hanubeki] + Source: http://code.google.com/r/hanubeki-modified-sm-ssc/source/detail?r=97761b5dc87b8c8a1b296985a09814337578c745 + +2012/05/27 +---------- +* [MusicWheel] Added EmptyColor metric. [AJ] +* [PlayerState] Enabled GetPlayerController Lua binding. + +2012/05/21 +---------- +* [NotesLoaderBMS] Support for #BMP based background changes. [theDtTvB] +* [SongManager] Add song to the list of songs before loading it, this fixes + crashes in some BMS files. [theDtTvB] +* [ScreenEdit] Allow a new way of creating and modifying attacks using the + Area Menu. Note: Using the C or V keys is no longer allowed for attacks. + It will simplify things for later. [Wolfman2000] +* [Steps] Modified HasSignificantTimingChanges; the following now disqualify + when using a CMod: Stops, Delays, Warps, Speed Changes, Scroll Changes. + Songs with a non-constant BPM will only disqualify if the High/Low difference + is greater than 3.00. [AJ] + +2012/05/19 +---------- +* [Actor] Made the xy command a source-code level command. + +2012/05/17 +---------- +* [LoadingWindow_Gtk] Actually resolve the path to the Splash file. [djpohly] + +2012/05/16 +---------- +* [ScreenWithMenuElements] Added DelayMusicSeconds metric. [AJ] +* [ScreenOptionsMasterPrefs] Allow for FastLoadAdditionalSongs preference + to be called via the "conf" command. [AJ] + +2012/05/14 +---------- +* [Course] Added AllSongsAreFixed() Lua binding. [AJ] + +================================================================================ +StepMania 5.0 alpha 2 | 20120504 +-------------------------------------------------------------------------------- + +2012/05/03 +---------- +* Add Var "Player" and Var "Controller" for NoteSkin. [hanubeki] + Sourced from http://code.google.com/r/hanubeki-modified-sm-ssc/source/detail?r=824cff29912d1c29a667046ba463d195e81c524a +* [CustomSpeedMods] If a player decides to remove 1x from the machine profile's + custom speed mods, re-add it back in to avoid crashes. [AJ] + +2012/05/02 +---------- +* Make ReceptorArrowRow and GhostArrowRow respect the column draw order. [hanubeki] + Sourced from http://code.google.com/r/hanubeki-modified-sm-ssc/source/detail?r=8ccf7449651eef51e8c42d031aa64da49a0b72ce + +2012/04/25 +---------- +* [Profile] Added GetLastPlayedSong and GetLastPlayedCourse Lua bindings. [AJ] + +2012/04/22 +---------- +* [LifeMeterBar] Reverted a change from 2010 that messed with how the life meter + subtracts life. The life difficulty should match StepMania 3.9 again. [AJ] + +2012/04/08 +---------- +* [ScreenNetworkOptions] Fixed a bug where localized text would not show up + properly. Fixes issue 759. [AJ] +* [Steps, Song] Replace Steps:UsesSplitTiming with + Song:IsStepsUsingDifferentTiming for both C++ and Lua. [wolfman2000] + +2012/04/06 +---------- +* Modify Jousway's planned noteskin to allow it to work with Technomotion + style gameplay. Expect minor bugs. [Jousway, Wolfman2000] + +2012/04/03 +---------- +* [PlayerOptions] Fix setting some effect mods that were always set to Drunk. + I wonder who had too much to drink. [TaroNuke] + +2012/03/31 +---------- +* [GameManager] Allow beat single7 and versus7 to be shown in Demonstration. [AJ] + +2012/03/28 +---------- +* [ScoreKeeperRave] Actually handle hold scores in HandleHoldScore(). + Players should please provide feedback on how this affects gameplay, as this + is a temporary feature. [AJ] +* [GameConstantsAndTypes] Made StageResult Lua-aware. [AJ] +* [GameState] Added GetStageResult(pn) Lua binding. [AJ] +* [Player] Keysounds now respect the volume settings. [hanubeki] + Sourced from hanubeki-modified-sm-ssc rev. 16fc5b714582 + +2012/03/27 +---------- +* [ScreenEditMenu] Don't hardcode stopping the music on pressing the back button. + This interferes with the StopMusicOnBack metric. [AJ] + +2012/03/20 +---------- +* [Background] Fix 3D noteskins and dancing characters from clashing with each other. [shakesoda, AJ] +* [NoteField] Fix 3D noteskins overlapping. [shakesoda, AJ] +* [ScreenEdit] Don't use Step timing by default. [Midiman] +* [ScreenEdit] Allow playback of course modifiers in Course Edit mode [Midiman] + +2012/03/15 +---------- +* [04 Scoring.lua] Added various 3.9 and 3.9+ scoring methods. [hanubeki] + +2012/03/12 +---------- +* Remove libtheora support since ffmpeg already supports theora videos. [cvpcs] + +2012/03/10 +---------- +* Update ffmpeg support to v0.10. [cvpcs] + +2012/03/09 +---------- +* [PlayerOptions] Don't display x-mods when using m-mods. + Sourced from hanubeki-modified-sm-ssc rev. bd08a58dd7cf and OpenITG. + +2012/03/08 +---------- +* [MusicWheel] Added RouletteStopped message, which is broadcast when Roulette + is finished and the wheel is locked. [AJ] +* [WheelBase] Made WheelState a Lua-enabled enum and added + GetWheelState() Lua binding. Deprecated IsLocked() Lua binding. [AJ] + +2012/03/07 +---------- +* [ScreenSelectMaster] Now updates choices on player join; it will move the + scroller to the correct location, but the GainFocus/LoseFocus commands don't + seem to work. [AJ] + +2012/03/05 +---------- +* [GameCommand] Added GetDifficulty(), GetCourseDifficulty(), GetPlayMode(), + GetSortOrder(), GetAnnouncer(), GetPreferredModifiers(), and + GetStageModifiers() Lua bindings. [AJ] + +2012/03/04 +---------- +* [Player] Changed default Hold window to 0.250f, like it was in 3.9. [AJ] + +2012/03/02 +---------- +* [NotesLoaderBMS] Fix calculating stops, Support for #LNOBJ, Don't use #BACKBMP + as song background if main StepsType is beat-*. [hanubeki] + These changes constitute revisions f26caccf103e, 2d114b38c6c9, and b60f021d2b67 + of hanubeki-modified-sm-ssc. (http://code.google.com/r/hanubeki-modified-sm-ssc/) + +2012/03/01 +---------- +* [MemoryCardManager] Disable Memory Cards by default. If you want to use them, +set MemoryCards=1 in Save/Preferences.ini (or Save/Static.ini). [AJ] +* [GameState] Set Premium to Premium_DoubleFor1Credit by default. [AJ] +* [ScreenSelectMusic] Added PlaySoundOnEnteringOptionsMenu metric. [AJ] +* [MusicWheel, WheelBase] Added collapse sound. [AJ] + +================================================================================ +StepMania 5.0 alpha 1a | 20120219 +-------------------------------------------------------------------------------- + +2012/02/19 +---------- +* [Style] Added LockedDifficulty() Lua binding. [AJ] + +2012/02/15 +---------- +* [HighScore] Added Max Combo, Stage Award and Peak Award. New Lua bindings for + HighScore: GetMaxCombo(), GetStageAward(), GetPeakComboAward(). [AJ] + (the specifics of this are subject to change.) + +2012/02/10 +---------- +* [WheelBase, WheelItemBase] Turned WheelItemDataType into a Lua type, + made WheelBase:GetSelectedType() return the enum instead of a number. [AJ] + +2012/02/08 +---------- +* [ScreenEdit] Added support for editing keysounds. Use the Area Menu (Enter) + to either modify what sounds play on that row, or even remove a sound from + the list. Any sounds assigned to empty notes will automatically become + an AutoKeysound, and any AutoKeysounds that have their sound removed will + become empty notes. [Wolfman2000] + +2012/02/08 +---------- +* [ScreenOptionsMaster] Added StepsRowLayoutType metric. + (Valid values are "ShowAllInRow" or "ShowOneInRow".) [AJ] + +2012/01/23 +---------- +* [Player] Tap Note Scores (tns) can now be "AvoidMine" or "HitMine" in +JudgmentMessageCommand. [Saturn2888, shakesoda] + +2012/01/15 +---------- +* [WheelNotifyIcon] Add the NumIconsToShow metric. [Wolfman2000] +* [PlayerOptions] Fix a problem with m-mods where you would get m200 as + the default speed modifier. [AJ] + +2012/01/11 +---------- +* [ScreenEdit] Fix a floating point issue when dealing with speed segments. + [Wolfman2000] + +2012/01/09 +---------- +* [Song] Fix a bug introduced with "Only read certain tags during first load" + where song graphic files wouldn't load. [theDtTvB] + +================================================================================ +StepMania 5.0 alpha 1 | 20120108 +-------------------------------------------------------------------------------- + +2012/01/08 +---------- +* [Song] Add HasPreviewVid and GetPreviewVidPath lua binding [cerbo] + +2012/01/08 +---------- +* [ScreenManager] Made AddScreenToTop take a second (optional) parameter for + posting a ScreenMessage on screen pop. [AJ] +* Only read certain tags during first load; makes song loading faster. [theDtTvB] + +2012/01/07 +---------- +* Fix Portable.ini not working on Mac OS X. [shakesoda] + +2012/01/05 +---------- +* [PercentageDisplay] Remove unused ApplyScoreDisplayOptions metric; + added PercentFormat and RemainderFormat metrics. [AJ] +* Fix Portable.ini not working in Linux. [FSX] + +2012/01/04 +---------- +* Fix a scoring/grading bug with Lifts. [FSX] + +2011/12/27 +---------- +* [MusicWheel] Add IsRouletting Lua binding. [AJ] +* [LuaManager] Remove GetOSName Lua binding; use GetArchName instead. [AJ] + +2011/12/26 +---------- +* [ArchHooks_OSX] Worked around a crash when language detection goes wrong. + Note: a real fix should be looked into. [shakesoda] + +2011/12/23 +---------- +* [Song] Fixed a bug where a sample start of 0 wouldn't work. [AJ] +* [Game] Added CountNotesSeparately and GetMapJudgmentTo(TapNoteScore) + Lua bindings. [AJ] +* [StepMania.cpp] Fix initial aspect ratio on first boot, hopefully. + (See issues 6 and 27) [AJ] + +2011/12/22 +---------- +* [LuaManager] Added ProductFamily() Lua binding. [AJ] + +2011/12/17 +---------- +* [Various] Allow loading of *.jpeg in addition to *.jpg. [AJ] + +2011/12/16 +---------- +* [StreamDisplay] Added VelocityMultiplier, VelocityMin, VelocityMax, + SpringMultiplier and ViscosityMultiplier metrics. [AJ] + +2011/12/12 +---------- +* [ScreenEdit] Add the GAMESTATE:InStepEditor Lua binding. [Wolfman2000] +* [Player, ScreenGameplay] Allow failing on Oni without crashing. This one + took awhile. [Wolfman2000] +* [LifeMeterBattery] Fixed various issues (lives not fully disappearing on fail, + P2 lose life animation having the wrong x zoom, hide the lives number if it + falls below 0). [AJ] + +2011/12/11 +---------- +* [ScreenEdit] Restore cycling the timing segments for jumping between. + The required line somehow never got replaced. [Wolfman2000] + +2011/11/30 +---------- +* [PlayerOptions] Added IsEasierForSongAndSteps(Song,Steps,PlayerNumber) and + IsEasierForCourseAndTrail(Course, Trail) Lua bindings. [AJ] +* [PlayerState] Added GetSuperMeterLevel() Lua binding. [AJ] + +2011/11/28 +---------- +* [ScreenGameplay] Add the SurvivalModOverride metric. Let the themer decide + if mods should be overridden on survival or not. Funny enough, this used + to be true for the old Oni style mode, but...well, we'll cross that bridge + later. [Wolfman2000] +* [LifeMeterBattery] Added MaxLives metric, which limits the maximum amount of + lives. Setting this to 0 will remove the limit. [AJ] + +2011/11/27 +---------- +* [PlayerOptions] Pretty large changes here, namely a bunch of new bindings. + Fixed the logic for GetReversePercentForColumn; It will now return nil for + invalid columns. Also fixed the logic for UsingReverse (now checks for 1.0f) + and SetPassmark (no longer allows values < 0.00f and > 1.0f). [AJ] +* [ScreenEdit] Allow inserting and removing beats and timing changes in + specific note increments instead of just quarter notes (a whole beat). + Those that prefer to keep using the shortcut keys will note that the + behavior has not changed for that: only by going into the Area menu can you + deal with more specific changes. [Wolfman2000] + +2011/11/26 +---------- +* [ScreenEdit] Restore using F9 and F10 to adjust stops by a fixed amount. + Sorry for the delay in this. [Wolfman2000] +* [ScreenEdit] Minor convenience. If you attempt to create a negative stop + segment from scratch, it does not create, and you are not requested to + save on exit, for there is nothing to save. [Wolfman2000] +* [ScreenEdit] Allow Shift + F9/F10 for adjusting delays. This works the same + way as adjusting stops. [Wolfman2000] + +2011/11/25 +---------- +* [PlayerStageStats] Hitting a mine no longer gives you full combo when + [Gameplay] MineHitIncrementsMissCombo=true. [AJ] + +2011/11/24 +---------- +* [PlayerStageStats] Added GetFailed and GetNumControllerSteps Lua bindings. [AJ] + +2011/11/15 +---------- +* [LifeMeterBar] Added the ForceLifeDifficultyOnExtraStage metric and + the ExtraStageLifeDifficulty metric. Let the themer decide if extra stages + should have their own life bar behavior. Note that this metric does NOT + change the lifebar to the battery style. [Wolfman2000/FSX] + +2011/11/14 +---------- +* [Mac OS X] Restore JPEG functionality. [Wolfman2000] + +2011/11/06 +---------- +* [GameState] Add the RefreshNoteSkinData lua binding. This will only + refresh the NS data for the present game, not all games. [Wolfman2000] +* [ScreenSelectMusic] Fixed Rave difficulties not being synced on late join. + Fixes issue 577. [AJ] +* [GameplayAssist] Don't play sounds if the player is dead. Fixes issue 621. [AJ] + +2011/11/04 +---------- +* [ScoreKeeperRave] Revert fix from 2011/10/28. [AJ] +* [ScoreKeeperRave] Fixed Miss and HitMine giving meter life. + (Fixes issue 622.) [AJ] + +2011/11/02 +---------- +* [ArchHooks] Add the GetArchName lua binding. To the themers that use + GetOSName, that function may be deprecated in the future. For now, + both options exist. [vyhd, Wolfman2000] + +2011/11/01 +---------- +* [ArrowEffects] Fix Expand, and possibly other mods, from breaking if + using a second player. [Wolfman2000] +* [ArchHooks] Add the AppHasFocus lua binding. [vyhd, Wolfman2000] + +2011/10/29 +---------- +* [GameState] Add the ResetPlayerOptions lua binding. [Wolfman2000] + +2011/10/28 +---------- +* [ScoreKeeperRave] Fix an issue where the super meter would not decrease back + to 1 after hitting the end of 3. (Fixes issue 314.) [AJ] + +2011/10/27 +---------- +* [Default theme] Fixed the pref controlling timing segments on song meter. [FSX] + +2011/10/18 +---------- +* [LightsManager] Use song beat for menu button lights, allow demonstration to + flash pad lights when BlinkGameplayButtonLightsOnNote is true, light custom + game buttons when pressed during attract mode, general optimizations. [vyhd] + +2011/10/17 +---------- +* [ScreenEdit/NoteField] Fix an editor crash when you exit without saving + after creating new steps. [Wolfman2000] + +2011/10/16 +---------- +* [NoteDataUtil] Add the Backwards mod for games where the intended + definition of Mirror is different. Regarding Pump gameplay, what was + called Mirror in Preview 4 is considered Backwards now, and the original + Mirror is back in its old position. [Wolfman2000] + +2011/10/12 +---------- +* [Steps] Fix a bug where e.g. ".SM" ".DWI" ".Sm" ".sM" files + wouldn't properly load since the code was expecting lowercase. [AJ] + +2011/10/10 +---------- +* [NotesLoaderBMS] Add the time signature segments. [theDtTvB] + +2011/10/09 +---------- +* [NotesLoaderBMS] Fix the bug where keysounds that points to nonexistant file + gets assigned a random one. [theDtTvB] +* [NotesLoaderBMS] Use BMSLoader to load PMS files. [theDtTvB] +* [RageSoundReader_WAV] Fix ADPCM support. [theDtTvB] + +2011/10/08 +---------- +* [GameSoundManager] Add the PlayMusicPart lua binding. [Wolfman2000] +* [ScreenEdit] Add the FadeInPreview and FadeOutPreview metrics. This controls + how long the fade in and fade outs are for playing the preview music. + The default values are 0 and 1.5 respectively. [Wolfman2000] + +2011/10/07 +---------- +* [RageDisplay] Add the GetFPS, GetVPF, and GetCumFPS bindings. [Wolfman2000] + +2011/10/06 +---------- +* Various scoring fixes sourced from http://www47.atwiki.jp/waiei/pages/21.html + [A.C/@waiei, 桜為小鳩/@sakuraponila] + +================================================================================ +StepMania 5.0 Preview 4 | 20111005 +-------------------------------------------------------------------------------- + +2011/10/04 +---------- +* [NoteDataUtil] More accurate Left, Right, and Mirror mods for Pump gameplay. + Major thanks to Hudson Felker and Bill Shillito here. [Wolfman2000] + +2011/10/01 +---------- +* [ScreenHighScores] Disable forced screen transition behavior when + ManualScrolling=true. [AJ] + +2011/09/30 +---------- +* [GameState] Added CurrentOptionsDisqualifyPlayer(player), + ApplyPreferredModifiers(player,string) and ApplyStageModifiers(player,string) + Lua bindings. [AJ] + +2011/09/29 +---------- +* [Fallback theme] Fix ImmediateHoldLetGo function. [Wolfman2000] +* [GameState] Add the EditAllowedForExtra metric. Use this if you want edit + steps to be allowed for accessing the extra stage. By default, this is + false. [Wolfman2000] + +2011/09/26 +---------- +* [Default theme] Added Song Timing Display user preference. [AJ] +* [ThemeManager] Add global Scripts dir. [shakesoda] + +2011/09/25 +---------- +* [WheelItemBase] Added GetColor and GetText Lua bindings. [AJ] + +2011/09/24 +---------- +* [ScreenEdit] Disable shifting timing changes down one beat if starting on + beat 0. Important information must stay on that beat. [Wolfman2000] +* [ScreenEdit] Disable converting rows to a stop or beat starting on beat 0. + There should be no reason for this at this time. [Wolfman2000] +* [MusicWheelItem] Add/reinstate MusicWheelItem Mode Normal/Color/OverPart. [AJ] +* [FadingBanner] Added LoadFromSortOrder(SortOrder) Lua binding. [AJ] + +2011/09/23 +---------- +* [ScreenEvaluation] Added RollingNumbersMaxComboClass metric. [AJ] +* [NotesLoaderSM] Fix loading .sm files with non standard difficulty names. + It should be Hard, not Heavy. [Wolfman2000] + +2011/09/22 +---------- +* [ScreenDebugOverlay] Replaced hardcoded toggle command with + ButtonTextToggledCommand metric. [AJ] +* [LoadingWindow_Win32] Make the StepMania window gain focus after the + loading window closes. Fixes issue 424. [AJ] + +2011/09/21 +---------- +* [FadingBanner] Added LoadRandom(), LoadRoulette(), LoadFallback(), + LoadCourseFallback(), and GetBanner(int) Lua bindings. [AJ] + +2011/09/18 +---------- +* [Song] Added GetSampleStart() and GetSampleLength() Lua bindings. [Wolfman2000] + +2011/09/16 +---------- +* [UnlockManager] Added GetNumLockedSongs() Lua binding. [Wolfman2000] +* [UnlockManager] Added IsSongLocked() Lua binding. [Wolfman2000] + +2011/09/12 +---------- +* [NotesLoaderSSC/WriterSSC] Allow all timing tags regardless of what timing + is used. [Wolfman2000] + +2011/09/11 +---------- +* [ScreenEvaluation] Added "evaluation full combo W1" and + "evaluation full combo W2" announcer cues. [AJ] +* [Banner] Added "Banner group fallback" graphic. [AJ] + +2011/09/09 +---------- +* [NotesLoaderBMS] Rewrite the BMS loader, should fix issues 430 and 500. [theDtTvB] + +2011/09/08 +---------- +* [GameManager] Fix shifting of 2P notes in beat mode. [1a2a3a2a1a] + +2011/09/07 +---------- +* [Model] Added GetDefaultAnimation() Lua binding. [AJ] +* [GameState] Added GetEarnedExtraStage() Lua binding. [AJ] + +2011/09/02 +---------- +* [MenuTimer] Added start(), disable() Lua bindings. Also renamed setseconds to + SetSeconds to match GetSeconds. [AJ] +* [GameManager] beat "versus" -> "versus5"; fix beat versus7 being "single7". [1a2a3a2a1a] + +2011/08/27 +---------- +* Updated libjpeg to 8c. +* [SongManager] Added GetCoursesInGroup(sCourseGroup,bIncludeAutogen), + GetSongGroupBannerPath(songGroup), GetCourseGroupBannerPath(courseGroup), + DoesSongGroupExist(songGroup), DoesCourseGroupExist(courseGroup) and + GetPopularSongs() Lua bindings. [AJ] +* [SongManager] Added GetPreferredSortSongs(), GetPreferredSortCourses(courseType,bIncludeAutogen), + and GetPopularCourses(courseType) Lua bindings. [AJ] +* [SongManager] Add SongToPreferredSortSectionName(song), WasLoadedFromAdditionalSongs(song), + and WasLoadedFromAdditionalCourses(course) Lua bindings. [AJ] +* [CryptManager] Add GenerateRandomUUID() Lua binding. [AJ] +* [ThemeManager] Added DoesThemeExist(sTheme), IsThemeSelectable(sTheme), + DoesLanguageExist(sLang), GetCurThemeName(), HasMetric(sGroup,sValue), and + HasString(sGroup,sValue) Lua bindings. [AJ] + +2011/08/23 +---------- +* [Makefile.am] Fixed version date and time handling. [AJ] + +2011/08/22 +---------- +* [PrefsManager, X11Helper] Added ShowMouseCursor preference. [AJ] +* [UnlockManager] Added GetStepOfAllTypes Lua binding. This gets the locked + Steps for all game types based on the difficulty specified. [Wolfman2000] +* [UnlockManager] Added requirepasschallengesteps Lua binding. This is more + self-explanitory: pass challenge to be able to play edits. [Wolfman2000] + +2011/08/21 +---------- +* [NotesLoaderSSC] Fix loading pre-split timing files that had blank timing + tags inside of them. Thanks to Vin.il for the catch. [Wolfman2000] +* [Song] Added Jacket, CD image (a la early DDR), and Disc (PIU-style) support. + Added GetJacketPath(), GetCDImagePath(), GetDiscPath(), HasJacket(), HasDisc(), + and HasCDImage() Lua bindings. [AJ] + +================================================================================ +StepMania 5.0 Preview 3 | 20110820 +-------------------------------------------------------------------------------- + +2011/08/20 +---------- +* [PlayerOptions] Add GetMMod() Lua binding. [AJ] +* [Player] Make keysounds respect volume preference. Fixes issue 344. [AJ] + +2011/08/19 +---------- +* [Steps] Add PredictMeter() and GetDisplayBPMType() Lua bindings. [AJ] +* [Song] Add ShowInDemonstrationAndRanking() Lua binding. [AJ] +* Turn off Autogen by default. [shakesoda] +* Disable automatic aspect ratio guessing, default to 854x480 + (16:9 because most newer displays are wide). [shakesoda] +* Turn on FastLoad and FastLoadAdditionalSongs by default. [shakesoda] + +2011/08/18 +---------- +* [RageInput] Added "No input devices were loaded." string to languages. [AJ] +* [RageInputDevice] Added localized names for InputDeviceState. [AJ] +* [Course] Add IsPlayableIn(StepsType) and IsRanking() Lua bindings. [AJ] +* [Trail] Added GetTotalMeter(), GetLengthSeconds(), IsSecret() + and ContainsSong(song) Lua bindings. [AJ] + +2011/08/16 +---------- +* Added PrettyPercent(numerator,denominator) Lua binding. [AJ] + +2011/08/14 +---------- +* [Foreground] Restore Foreground Changes for use in gameplay. Note that it + is recommended to use lua for #FGCHANGES from now on: not all XML changes + will work. [infamouspat] + +2011/08/13 +---------- +* [Theme-side] Added Fancy UI Background preference to Theme Options. [AJ] +* [LowLevelWindow_X11] Don't force the window into the upper left corner. [ZipFile] + +2011/08/07 +---------- +* [LifeMeterBattery] Added LostLife param to LifeChanged message. [AJ] +* [LifeMeterBattery] Converted LifeMeterBattery lives to an AutoActor. [AJ] +* [TimingData] Add HasDelays() Lua binding; HasStops() now only checks stops. [AJ] +* [GameState, SongUtil] Fix Issue 263 by not charging 2x stages for doubles when + not using joint premium. [AJ] +* [BeginnerHelper] Made BeginnerHelper run the OnCommand. [AJ] +* [GameState] add GetExpandedSectionName() Lua binding. [AJ] +* [ScreenSelectMusic] Added IdleCommentSeconds metric and + "ScreenSelectMusic IdleComment" announcer sound. [AJ] +* [NotesLoaderBMS] "Send the actual song file to LoadFromBMSFile in + BMSLoader::LoadNoteDataFromSimfile instead of the dummy one... + This fixes the wrong sound issue [423]..." [theDtTvB] + +2011/08/06 +---------- +* [NoteSkins/beat/default] Fix Issue 425. [AJ] +* [ScoreDisplayRave] Allow (Meter/Level)(X/Y) metrics to work again. [AJ] + +2011/08/05 +---------- +* [NoteField] Added AreaHighlightColor metric. [AJ] + +2011/08/04 +---------- +* [NoteTypes, ScreenEdit] Removed artificial MAX_NOTES_PER_MEASURE limit. [AJ] + +2011/08/02 +---------- +* [NotesSSC] Only write timing/attack tags for the step if there is a + difference from the song. For timing tags, at this time it means that if even + one tag is different, all tags are written. [Wolfman2000] + +2011/08/01 +---------- +* [MusicWheel, RoomWheel] Moved the "- EMPTY -" string to the languages file. [AJ] + +2011/07/31 +---------- +* [ScreenGameplay, LyricDisplay] Stop lyrics from animating on failure. + Fixes issue 298. [AJ] + +2011/07/30 +---------- +* [ProfileManager] Fix an issue when deleting recently created profiles. [AJ] +* Start removing anything related to Guitar mode. This was rushed in, and it + is not worth us keeping at this time. [Wolfman2000] + +2011/07/26 +---------- +* [ScreenEdit] Add a semi working implementation of the often requested + copy/paste selected timing data feature. This should make it easier for + some charters. [Wolfman2000] + +2011/07/21 +---------- +* [BeginnerHelper] Removed DancePadAngle metric in favor of DancePadOnCommand. + The same goes for PlayerAngle, dancer rotation is now handled in + PlayerP1/2OnCommand. [AJ] +* [Course] Bumped up max edit course title length to 16 (still feels too short). + Also added #DESCRIPTION tag and Course:GetDescription() Lua binding. [AJ] + +2011/07/20 +---------- +* [Win32/CrashHandlerChild] Crashlog and log now open in the player's default + text editor. Also, the Show Log button works again, including for people using + Portable.ini. [AJ] + +2011/07/19 +---------- +* [LoadingWindow] Added the ability for themes to have custom splash banners. + (Currently Windows-only.) [AJ] + +2011/07/17 +---------- +* [Cache] No longer store #NOTES in the cache. This should speed things up + on the first load if there is not much to write. (General note: this was + taken from another branch, but results at that point were great.) + [Wolfman2000] + +2011/07/13 +---------- +* [Difficulty] Allow ALL StepsTypes to use CustomDifficulty properly. + There was some unfair targeting of Couple and Routine. [Wolfman2000] +* [Steps] Calculate accurate radar values for Couple charts. [Wolfman2000] +* [ScreenEdit] Display more accurate chart data for Couple and Routine charts + for the future. No more having (almost) every row as a jump! [Wolfman2000] + +2011/07/12 +---------- +* [OptionRowHandler] Add a new metric to ScreenOptionsMaster: + StepsUseChartName. Use this if you want your charts to have a unique name + in the options menu. If there is no #CHARTNAME or it is "Blank", it reverts + to the original behavior. This metric is false by default. [Wolfman2000] +* [ScreenEdit] Fixed a bug involving #ATTACKS. Now when you set an attack, + the mods are reverted back to how they were prior to the attack being set. + [Wolfman2000] + +2011/07/09 +---------- +* [NotesTheUsual] Update the #COMBOS tag to allow for a Miss Combo attribute. + Any files that only use the Combo attribute will have that value copied to + miss combo on next launch. [Wolfman2000] +* [ScoreKeeperNormal] Better match #COMBOS with eval. Scoring formulas should + not be affected, but it may require more testing. [Wolfman2000] +* [Metrics] Have Pump mode lump the checkpoint judgments with Flawless and + Miss judgments on eval. Of course, this goes down to Perfect and Miss if + that is disabled. [Wolfman2000] + +2011/07/07 +---------- +* [ScreenEdit] Fix the NoMines transformation bug, issue 363. [Wolfman2000] +* [CourseLoaderCRS] Don't load BEST# and WORST# where # is greater than the + number of songs installed. Fixes issue 373. [AJ] +* [NotesAllSSC] Add the #CHARTNAME tag to the Steps. #DESCRIPTION is now for + more detailed descriptions, or perhaps some short hand lingo. All files + that used #DESCRIPTION will have their values moved to #CHARTNAME on + load. [Wolfman2000] +* [ScreenEdit] Add a Steps Data menu for getting numerical step data on the + chart. This is a read only menu. Edit Steps Information contains writable + information. [Wolfman2000] +* [NotesAllSSC] Add the Steps version of #DISPLAYBPM. The Song version is + still there, so themes should not have to worry about breakage. + [Wolfman2000] + +2011/07/06 +---------- +* [ScreenEdit] Fix the bug where hitting Enter during playing wouldn't take + the user back to the editor. [Wolfman2000] +* [Gameplay] Fix Fail mods being dishonored. [Midiman] + +2011/07/05 +---------- +* [ScreenEdit] Restore dance-couple and pump-couple for editing purposes. + Saving should still work, but this was never tested yet. [Wolfman2000] +* [ScreenOptions] Mini is now ITG Mini, and Tiny is now Pump Pro Mini. + This will prevent many prior courses from breaking. [sharksoda, Wolfman2000] +* [CharacterManager] Add a lua function to check how many characters you have. + For an example of how this is used, check the default theme's scripts + folder, specifically 03 ThemePrefs.lua. [Wolfman2000] + +2011/07/04 +---------- +* [ScreenEdit] Add a function to switch the notes the routine players have to + hit. In simple terms, Player 1's notes are now Player 2's and vice~versa. + Check it out in the Alter Menu. [Wolfman2000] +* [ScreenEdit] Add two routine mirroring functions. Now you can build sections + of a chart for one player, and mirror the effect for the other player when + finished. For Pump players, it is not a straight mirror, but is more akin + to what is found via normal routine charts. In other words, you'll be happy. + Check it out in the Alter Menu. [Wolfman2000] + +2011/07/03 +---------- +* [ScreenEdit] Fix a crash if one tries to remove an attack that doesn't + exist at that time. [Wolfman2000] + +================================================================================ +StepMania 5.0 Preview 2 | 20110703 +-------------------------------------------------------------------------------- + +2011/07/03 +---------- +* [Player] Bring mMods from OpenITG over. Also, a metric was added, + "MModHighCap", to cap the speed mod if required for playing songs like + Tsuhsuixamush. Set the metric to 0 or less to remove the cap. [AJ, sharksoda, + Wolfman2000] + +2011/07/02 +---------- +* [ScreenEdit] Fixed a crash when hitting Enter in the F1 help menu. [AJ] + +2011/06/30 +---------- +* [NotesAll] Use #FIRSTSECOND, #LASTSECOND, and #LASTSECONDHINT instead of the + former BEAT equivalents. Split Timing has made this a necessity thanks to + certain files that abuse Stops/Delays more than usual. [Wolfman2000] +* [ScreenEdit] Add a function in the Area Menu to designate the current beat + as the last second of the song. Please try to be smart and not use this too + early. [Wolfman2000] + +2011/06/28 +---------- +* [ScreenEdit] Add a function to copy/paste the TimingData of a player's + choice. Remember to be in the appropriate mode when copying and pasting. + By default, the song timing is already located in the clipboard, ready for + use. [Wolfman2000] + +2011/06/27 +---------- +* [Steps] Make sure #ATTACKS are copied when requested. [Wolfman2000] +* [ScreenEdit] Have Step Author up front instead of Chart Style. This is + probably going to be better overall. [Wolfman2000] +* [TimingData] Preserve the length of time for Speed Segment scaling when using + beats. [Wolfman2000] +* [NotesLoader/WriterSSC] #OFFSET is to be before #ATTACKS. This is required if + we pursue beat based attacks and not just second based. [Wolfman2000] + +2011/06/26 +---------- +* [UnlockManager] New metric: AutoLockEditSteps. Use this to hide bonus charts + until the Expert steps are beaten. No guarantee that this works with no + challenge steps in the song. This defaults to false. [Wolfman2000] +* [UnlockManager] New metric: SongsNotAdditional. Set to true to keep the + default behavior, false to have the AdditionalSongs folder contain + unlockable material. This is set to true to start. [Wolfman2000] +* [ScreenEdit] Allow jumping between all segments, not just Label segments. + You still use Ctrl + ,/. to jump, but now you use Ctrl + N/M to cycle the + segments. By default, it starts with Label. [Wolfman2000] +* [PlayerOptions] No longer display StepAttacks in the player's list. + Instead, show NoAttacks if attacks are disabled. [Wolfman2000] + +2011/06/24 +---------- +* [Actor] Implement compound(length,tweens) in _fallback/02 Actor.lua. [AJ] +* [UnlockManager] Add a new unlock reward: StepsType. This is similar to + unlocking Steps, but it is targeted for one step in one stepstype rather + than one step in all stepstypes. This needs testing. [Wolfman2000] +* [ScreenEdit] Add the option to convert delays to beats. Just find a better + song to use this on besides Uprock. [Wolfman2000] +* [ScreenEdit] Fix a crash if you don't save any steps on a new song. + [Wolfman2000] +* [NotesLoader/WriterSSC] Add support for Step #ATTACKS. Furthermore, Song + Attacks (or rather, Step Attacks as it should be called now) are turned on + by default instead of off. [Wolfman2000] + +2011/06/19 +---------- +* [EditMenu] Allow all songs to work in Practice Mode, regardless of folder + location. This fixes a crash if everyone had songs in AdditionalSongs. + [Wolfman2000] + +2011/06/17 +---------- +* [LifeMeterBattery] Fixed a bug where MinesSubtractLives was not being honored. + Also added LifeChanged message to changing of life on holds. [AJ] + +2011/06/15 +---------- +* [TimingData] Added many lua bindings for the other timing segments. GetWarps, + GetCombos, GetTimeSignatures, GetTickcounts, GetFakes, GetScrolls, GetSpeeds. + This should cover all of them now. [Wolfman2000] + +2011/06/13 +---------- +* [InputHandler_DirectInput] Fixed MouseWheel input not resetting. [AJ] +* [ScreenTextEntry] Make it so only the keyboard's Enter key can finish the + screen. Should fix issues with buttons whose secondary function is MenuStart. [AJ] +* [InputMapper] Modify default mappings. Use the Hyphen key instead of the + Numlock key for Player 2's GAME_BUTTON_BACK. This should address some + issues with Player 2 being unable to back out if they use a laptop. + [Wolfman2000] +* [NoteDisplay] Add two new metrics. + * DrawRollHeadForTapsOnSameRow: bool, similar to DrawHoldHeadForTapsOnSameRow + * TapHoldRollOnRowMeansHold: bool, true means hold and false means roll + * No noteskins should require updating, as these were placed in common/common + for ease of use. [Wolfman2000] +* [LifeMeterBattery] Added ChangeLives(int) Lua binding. [AJ] +* [LifeMeterBattery] Added DangerThreshold metric. [AJ] +* [LifeMeterBattery] Added some important metrics. [AJ] + * MinScoreToKeepLife='TapNoteScore_*' - any score below this = loss of life. + * SubtractLives=1 - how many lives are lost when going below MinScoreToKeepLife. + * MinesSubtractLives=1 - how many lives are lost when hitting a mine. + * HeldAddLives=0 - how many lives are gained when a hold is completed. + * LetGoSubtractLives=1 - how many lives are lost on a dropped hold. + +2011/06/12 +---------- +* [ScreenNetSelectMusic] Add PlayerOptionsScreen metric. [AJ] +* [ScreenEdit] Restore the old PageUp/PageDown behavior, added Control + + PageUp/PageDown to use recent time signature behavior. Laptop users, that + includes you guys too: semicolon and apostrophe are still good. [Wolfman2000] + +2011/06/11 +---------- +* [ScreenEdit] Allow setting the Music Preview via the Alter Menu. Just select + your area, enter the menu, and choose "Designate as Music Preview". No more + math calculations needed! [Wolfman2000] +* [SongUtil] Added GetPlayableSteps(Song) Lua binding. [AJ] +* [Steps] Allow 255 characters for all chart descriptions, including edits. + We are no longer bound by In The Groove I think. [Wolfman2000] +* [Player] Add GetPlayerTimingData() Lua binding. [Wolfman2000] + +2011/06/10 +---------- +* [ScreenEdit] Split the Area Menu into the Area Menu and Alter Menu. Use the + "A" key to enter the Alter Menu when a selection of notes/rows are + highlighted. Use the Enter key to enter the old Area Menu for the options that + do not depend on selecting NoteData. [Wolfman2000] +* [ScreenEdit] Allow converting selections to Delays, Warps, or Fakes as well + as Stops. Remember, use the Alter Menu for this. [Wolfman2000] + +2011/06/09 +---------- +* [ScreenSyncOverlay] Ensure that F11 / F12 work with all charts due to Split + Timing. [Wolfman2000] + +2011/06/08 +---------- +* Any notes in a fake segment or warp segment are completely ignored for + scoring purposes. Now you can get 100% on your warping goodness! + [Wolfman2000] + +2011/06/06 +---------- +* [PlayerOptions] Removed the ScoreDisplay mod choices. Use lua to make your + own scoring formulas that work in reverse instead. [Wolfman2000] +* [ScreenGameplay] Fix an assist tick bug if there was no Player 1. Note that + this changes the behavior slightly: it is the first enabled player, or + master player, that gets the ticks now. A better solution will be looked at + in the future. [Wolfman2000] +* [NoteDataUtil] Fix a radar issue involving hands. Unfortunately, this means + yet another cache reload for accuracy purposes. [Wolfman2000] + +2011/06/04 +---------- +* Changed default MusicWheelSwitchSpeed to 15 (was 10). [AJ] +* [AnnouncerManager] Fixed a bug where no announcers would be loaded. [AJ] +* Restored the UserPrefAutoSetStyle behavior. [Wolfman2000] +* [NotesLoaderSMA] Better way of identifying beats and seconds. [Wolfman2000] + +================================================================================ +StepMania 5.0 Preview 1a | 20110603 +-------------------------------------------------------------------------------- + +2011/06/03 +---------- +* [LifeMeterBattery] Added LivesLeft param to LifeChanged message. [AJ] +* [Windows] Set up directories for pictures and app data in their proper + location. [Henke] +* [NotesLoaderSM] Fix an Offset load bug. [Wolfman2000] + +2011/06/02 +---------- +* [BPMDisplay] Added SetFromSteps Lua binding. [AJ] +* [ScreenDebugOverlay] Switch the R and T keys to be Volume Down and Up + respectively. I have to admit, it makes more sense to have volume up be + on the right instead of the left. [Wolfman2000] +* [SongManager] Make autogen courses have "Autogen" as the Scripter. [AJ] + +2011/06/01 +---------- +* [TimingData] Added the HasScrollChanges lua binding. [Wolfman2000] +* [ScreenEdit] Fix Song Timing behaviors. [Wolfman2000] + +2011/05/31 +---------- +* [Player] Added the BattleRaveMirror metric. This determines if Battle and + Rave mode will have the two players with mirrored charts or not. By default, + this is set to true, preserving the ITG style behavior. [Wolfman2000] +* [TimingData] Added the HasScrollChanges lua binding. [Wolfman2000] + +================================================================================ +StepMania 5.0 Preview 1 | 20110529 +-------------------------------------------------------------------------------- + +2011/05/27 +---------- +* [ScreenEdit] Added the LoopOnChartEnd metric. Once you get to the end of + the chart while playing it in the editor, this controls whether it loops and + plays again, or simply stops. By default, this is true, replicating current + behavior. Set to false to replicate older StepMania behavior. [Wolfman2000] + +2011/05/26 +---------- +* [ScoreKeeperNormal] Added the MissComboIsPerRow metric. Similar to the + ComboIsPerRow metric, this determines how much miss combo is earned on missing + a row of notes. By default, this is true. Set to false to replicate Pump Pro + behavior. [Wolfman2000] + +2011/05/25 +---------- +* [NotesLoaderSSC/NotesWriterSSC] Added the ScrollSegments. Think BPM change, + but not. [theDtTvB] + +2011/05/23 +---------- +* [Steps] Added the UsesSplitTiming Lua binding. [Wolfman2000] + +2011/05/20 +---------- +* [CryptManager] Added SHA1File Lua binding. [AJ] + +2011/05/19 +---------- +* [BPMDisplay] Add CourseCycleSpeed metric. [AJ] + +2011/05/17 +---------- +* [NotesWriterSM] Write out OpenITG compatible SM files from here on out. + This includes turning Warps into Negative Stops. For those that wanted + negative BPMs specifically, my apologies, but stops are easier on math. + [Wolfman2000] + +2011/05/16 +---------- +* [ProfileManager] Added ProfileWasLoadedFromMemoryCard(PlayerNumber) + Lua binding. [AJ] +* Added #FAKES to the SSC format. Similar to the fake arrows, these blocks + prevent all judgments within the range. [Wolfman2000] +* Changed the syntax of #WARPS slightly. Now the second value is the relative + distance that is skipped, not the absolute value when you start hitting + arrows again. [Wolfman2000] + +2011/05/15 +---------- +* [ScreenGameplay] Removed hardcoded commands for Debug (give up text) and + replace them with DebugStartOnCommand, DebugBackOnCommand, and + DebugTweenOffCommand. [AJ] +* Added #SPEEDS to the SSC format. This multiplies your scrolling speed during + gameplay, not replaces it (see mod attacks for replacing). [Wolfman2000] + +2011/05/14 +---------- +* [ModIcon] Added StopWords metric. [AJ] +* [ScreenSelectMaster] Add "ScreenEmpty" param to MenuStartP# when the GameCommand + doesn't set a screen. [AJ] +* [StepsDisplay] Added MeterFormatString metric. [AJ] +* [MusicWheel] Added ShowSectionsInBPMSort and ShowSectionsInLengthSort metrics. [AJ] +* [ScreenEvaluation] Stop the Bonus bars from overflowing in course modes. [AJ] +* [Banner] Added ScrollMode and ScrollSortOrder metrics. [AJ] + +2011/05/13 +---------- +* Added Split Timing to .SSC files. All older .SSC files and other file + formats are converted to split timing on cache load. We are no longer bound + by Song Timing for everything. [theDtTvB, Wolfman2000, TeruFSX] + +2011/05/11 +---------- +* [GameSoundManager] Added PlayAnnouncer Lua binding. [AJ] +* [AnnouncerManager] Add support for "gameplay combo #" for announcer. [AJ] + +2011/05/10 +---------- +* [Sprite] Added SetSecondsIntoAnimation Lua binding. [AJ] +* [BPMDisplay] Added SetFromCourse Lua binding. [AJ] + +2011/05/03 +---------- +* [ScreenEdit] Allow changing the Beat 0 Offset, Music Sample Start, and + Music Sample Length via Edit Song Info menu. [Wolfman2000] + +2011/05/02 +---------- +* [ScreenSelectMusic] Added NullScoreString metric. [AJ] + +2011/04/17 +-------- +* Use lua for all primary score keeping. Course modes right now still use the + old fashioned system. [TeruFSX, Wolfman2000] + +2011/04/09 +-------- +* [Player] Force hold judgments to take place before setting the score. + [theDtTvB] + +2011/04/05 +-------- +* [NotesLoaderSSC, NotesWriterSSC] Add the #LABELS tag. This is meant for step + editors to label different parts of their stepcharts. Use Control + , or . to + jump to different labels made. [Wolfman2000] + diff --git a/src/ProfileManager.cpp b/src/ProfileManager.cpp index 110cff47b5..a22b027ed1 100644 --- a/src/ProfileManager.cpp +++ b/src/ProfileManager.cpp @@ -1,888 +1,890 @@ -#include "global.h" -#include "ProfileManager.h" -#include "Profile.h" -#include "RageUtil.h" -#include "PrefsManager.h" -#include "RageLog.h" -#include "RageFile.h" -#include "RageFileManager.h" -#include "GameConstantsAndTypes.h" -#include "SongManager.h" -#include "GameState.h" -#include "Song.h" -#include "Steps.h" -#include "Course.h" -#include "GameManager.h" -#include "ProductInfo.h" -#include "RageUtil.h" -#include "ThemeManager.h" -#include "MemoryCardManager.h" -#include "XmlFile.h" -#include "StepsUtil.h" -#include "Style.h" -#include "HighScore.h" -#include "Character.h" -#include "CharacterManager.h" - - -ProfileManager* PROFILEMAN = NULL; // global and accessable from anywhere in our program - -static void DefaultLocalProfileIDInit( size_t /*PlayerNumber*/ i, RString &sNameOut, RString &defaultValueOut ) -{ - sNameOut = ssprintf( "DefaultLocalProfileIDP%d", int(i+1) ); - defaultValueOut = ""; -} - -Preference ProfileManager::m_bProfileStepEdits( "ProfileStepEdits", true ); -Preference ProfileManager::m_bProfileCourseEdits( "ProfileCourseEdits", true ); -Preference1D ProfileManager::m_sDefaultLocalProfileID( DefaultLocalProfileIDInit, NUM_PLAYERS ); - -const RString NEW_MEM_CARD_NAME = ""; -const RString USER_PROFILES_DIR = "/Save/LocalProfiles/"; -const RString MACHINE_PROFILE_DIR = "/Save/MachineProfile/"; -const RString LAST_GOOD_SUBDIR = "LastGood/"; - - -// Directories to search for a profile if m_sMemoryCardProfileSubdir doesn't -// exist, separated by ";": -static Preference g_sMemoryCardProfileImportSubdirs( "MemoryCardProfileImportSubdirs", "" ); - -static RString LocalProfileIDToDir( const RString &sProfileID ) { return USER_PROFILES_DIR + sProfileID + "/"; } -static RString LocalProfileDirToID( const RString &sDir ) { return Basename( sDir ); } - -struct DirAndProfile -{ - RString sDir; - Profile profile; -}; -static vector g_vLocalProfile; - - -static ThemeMetric FIXED_PROFILES ( "ProfileManager", "FixedProfiles" ); -static ThemeMetric NUM_FIXED_PROFILES ( "ProfileManager", "NumFixedProfiles" ); -#define FIXED_PROFILE_CHARACTER_ID( i ) THEME->GetMetric( "ProfileManager", ssprintf("FixedProfileCharacterID%d",int(i+1)) ) - - -ProfileManager::ProfileManager() -{ - m_pMachineProfile = new Profile; - FOREACH_PlayerNumber(pn) - m_pMemoryCardProfile[pn] = new Profile; - - // Register with Lua. - { - Lua *L = LUA->Get(); - lua_pushstring( L, "PROFILEMAN" ); - this->PushSelf( L ); - lua_settable( L, LUA_GLOBALSINDEX ); - LUA->Release( L ); - } -} - -ProfileManager::~ProfileManager() -{ - // Unregister with Lua. - LUA->UnsetGlobal( "PROFILEMAN" ); - - SAFE_DELETE( m_pMachineProfile ); - FOREACH_PlayerNumber(pn) - SAFE_DELETE( m_pMemoryCardProfile[pn] ); -} - -void ProfileManager::Init() -{ - FOREACH_PlayerNumber( p ) - { - m_bWasLoadedFromMemoryCard[p] = false; - m_bLastLoadWasTamperedOrCorrupt[p] = false; - m_bLastLoadWasFromLastGood[p] = false; - m_bNeedToBackUpLastLoad[p] = false; - m_bNewProfile[p] = false; - } - - LoadMachineProfile(); - - RefreshLocalProfilesFromDisk(); - - if( FIXED_PROFILES ) - { - // resize to the fixed number - if( (int)g_vLocalProfile.size() > NUM_FIXED_PROFILES ) - g_vLocalProfile.erase( g_vLocalProfile.begin()+NUM_FIXED_PROFILES, g_vLocalProfile.end() ); - - for( int i=g_vLocalProfile.size(); iGetCharacterFromID( sCharacterID ); - ASSERT_M( pCharacter, sCharacterID ); - RString sProfileID; - bool b = CreateLocalProfile( pCharacter->GetDisplayName(), sProfileID ); - ASSERT( b ); - Profile* pProfile = GetLocalProfile( sProfileID ); - ASSERT_M( pProfile, sProfileID ); - pProfile->m_sCharacterID = sCharacterID; - SaveLocalProfile( sProfileID ); - } - - ASSERT( (int)g_vLocalProfile.size() == NUM_FIXED_PROFILES ); - } -} - -bool ProfileManager::FixedProfiles() const -{ - return FIXED_PROFILES; -} - -ProfileLoadResult ProfileManager::LoadProfile( PlayerNumber pn, RString sProfileDir, bool bIsMemCard ) -{ - LOG->Trace( "LoadingProfile P%d, %s, %d", pn+1, sProfileDir.c_str(), bIsMemCard ); - - ASSERT( !sProfileDir.empty() ); - ASSERT( sProfileDir.Right(1) == "/" ); - - - m_sProfileDir[pn] = sProfileDir; - m_bWasLoadedFromMemoryCard[pn] = bIsMemCard; - m_bLastLoadWasFromLastGood[pn] = false; - m_bNeedToBackUpLastLoad[pn] = false; - - // Try to load the original, non-backup data. - ProfileLoadResult lr = GetProfile(pn)->LoadAllFromDir( m_sProfileDir[pn], PREFSMAN->m_bSignProfileData ); - - RString sBackupDir = m_sProfileDir[pn] + LAST_GOOD_SUBDIR; - - if( lr == ProfileLoadResult_Success ) - { - /* Next time the profile is written, move this good profile into LastGood. */ - m_bNeedToBackUpLastLoad[pn] = true; - } - - m_bLastLoadWasTamperedOrCorrupt[pn] = lr == ProfileLoadResult_FailedTampered; - - // - // Try to load from the backup if the original data fails to load - // - if( lr == ProfileLoadResult_FailedTampered ) - { - lr = GetProfile(pn)->LoadAllFromDir( sBackupDir, PREFSMAN->m_bSignProfileData ); - m_bLastLoadWasFromLastGood[pn] = lr == ProfileLoadResult_Success; - - /* If the LastGood profile doesn't exist at all, and the actual profile was failed_tampered, - * then the error should be failed_tampered and not failed_no_profile. */ - if( lr == ProfileLoadResult_FailedNoProfile ) - { - LOG->Trace( "Profile was corrupt and LastGood for %s doesn't exist; error is ProfileLoadResult_FailedTampered", - sProfileDir.c_str() ); - lr = ProfileLoadResult_FailedTampered; - } - } - - LOG->Trace( "Done loading profile - result %d", lr ); - - return lr; -} - -bool ProfileManager::LoadLocalProfileFromMachine( PlayerNumber pn ) -{ - RString sProfileID = m_sDefaultLocalProfileID[pn]; - if( sProfileID.empty() ) - { - m_sProfileDir[pn] = ""; - return false; - } - - m_sProfileDir[pn] = LocalProfileIDToDir( sProfileID ); - m_bWasLoadedFromMemoryCard[pn] = false; - m_bLastLoadWasFromLastGood[pn] = false; - - if( GetLocalProfile(sProfileID) == NULL ) - { - m_sProfileDir[pn] = ""; - return false; - } - - return true; -} - -void ProfileManager::GetMemoryCardProfileDirectoriesToTry( vector &asDirsToTry ) -{ - /* Try to load the preferred profile. */ - asDirsToTry.push_back( PREFSMAN->m_sMemoryCardProfileSubdir ); - - /* If that failed, try loading from all fallback directories. */ - split( g_sMemoryCardProfileImportSubdirs, ";", asDirsToTry, true ); -} - -bool ProfileManager::LoadProfileFromMemoryCard( PlayerNumber pn, bool bLoadEdits ) -{ - UnloadProfile( pn ); - - // mount slot - if( MEMCARDMAN->GetCardState(pn) != MemoryCardState_Ready ) - return false; - - vector asDirsToTry; - GetMemoryCardProfileDirectoriesToTry( asDirsToTry ); - m_bNewProfile[pn] = true; - - for( unsigned i = 0; i < asDirsToTry.size(); ++i ) - { - const RString &sSubdir = asDirsToTry[i]; - RString sDir = MEM_CARD_MOUNT_POINT[pn] + sSubdir + "/"; - - /* If the load fails with ProfileLoadResult_FailedNoProfile, keep searching. However, - * if it fails with failed_tampered, data existed but couldn't be loaded; - * we don't want to mess with it, since it's confusing and may wipe out - * recoverable backup data. The only time we really want to import data - * is on the very first use, when the new profile doesn't exist at all, - * but we also want to import scores in the case where the player created - * a directory for edits before playing, so keep searching if the directory - * exists with exists with no scores. */ - ProfileLoadResult res = LoadProfile( pn, sDir, true ); - if( res == ProfileLoadResult_Success ) - { - m_bNewProfile[pn] = false; - /* If importing, store the directory we imported from, for display purposes. */ - if( i > 0 ) - m_sProfileDirImportedFrom[pn] = asDirsToTry[i]; - break; - } - - if( res == ProfileLoadResult_FailedTampered ) - { - m_bNewProfile[pn] = false; - break; - } - } - - /* If we imported a profile fallback directory, change the memory card - * directory back to the preferred directory: never write over imported - * scores. */ - m_sProfileDir[pn] = MEM_CARD_MOUNT_POINT[pn] + (RString)PREFSMAN->m_sMemoryCardProfileSubdir + "/"; - - /* Load edits from all fallback directories, newest first. */ - if( bLoadEdits ) - { - for( unsigned i = 0; i < asDirsToTry.size(); ++i ) - { - const RString &sSubdir = asDirsToTry[i]; - RString sDir = MEM_CARD_MOUNT_POINT[pn] + sSubdir + "/"; - - if( m_bProfileStepEdits ) - SONGMAN->LoadStepEditsFromProfileDir( sDir, (ProfileSlot) pn ); - if( m_bProfileCourseEdits ) - SONGMAN->LoadCourseEditsFromProfileDir( sDir, (ProfileSlot) pn ); - } - } - - return true; // If a card is inserted, we want to use the memory card to save - even if the Profile load failed. -} - -bool ProfileManager::LoadFirstAvailableProfile( PlayerNumber pn, bool bLoadEdits ) -{ - if( LoadProfileFromMemoryCard(pn, bLoadEdits) ) - return true; - - if( LoadLocalProfileFromMachine(pn) ) - return true; - - return false; -} - - -bool ProfileManager::FastLoadProfileNameFromMemoryCard( RString sRootDir, RString &sName ) const -{ - vector asDirsToTry; - GetMemoryCardProfileDirectoriesToTry( asDirsToTry ); - - for( unsigned i = 0; i < asDirsToTry.size(); ++i ) - { - const RString &sSubdir = asDirsToTry[i]; - RString sDir = sRootDir + sSubdir + "/"; - - Profile profile; - ProfileLoadResult res = profile.LoadEditableDataFromDir( sDir ); - if( res == ProfileLoadResult_Success ) - { - sName = profile.GetDisplayNameOrHighScoreName(); - return true; - } - else if( res != ProfileLoadResult_FailedNoProfile ) - break; - } - - return false; -} - -bool ProfileManager::SaveProfile( PlayerNumber pn ) const -{ - if( m_sProfileDir[pn].empty() ) - return false; - - /* - * If the profile we're writing was loaded from the primary (non-backup) - * data, then we've validated it and know it's good. Before writing our - * new data, move the old, good data to the backup. (Only do this once; - * if we save the profile more than once, we haven't re-validated the - * newly written data.) - */ - if( m_bNeedToBackUpLastLoad[pn] ) - { - m_bNeedToBackUpLastLoad[pn] = false; - RString sBackupDir = m_sProfileDir[pn] + LAST_GOOD_SUBDIR; - Profile::MoveBackupToDir( m_sProfileDir[pn], sBackupDir ); - } - - bool b = GetProfile(pn)->SaveAllToDir( m_sProfileDir[pn], PREFSMAN->m_bSignProfileData ); - - return b; -} - -bool ProfileManager::SaveLocalProfile( RString sProfileID ) -{ - const Profile *pProfile = GetLocalProfile( sProfileID ); - ASSERT( pProfile != NULL ); - RString sDir = LocalProfileIDToDir( sProfileID ); - bool b = pProfile->SaveAllToDir( sDir, PREFSMAN->m_bSignProfileData ); - return b; -} - -void ProfileManager::UnloadProfile( PlayerNumber pn ) -{ - m_sProfileDir[pn] = ""; - m_sProfileDirImportedFrom[pn] = ""; - m_bWasLoadedFromMemoryCard[pn] = false; - m_bLastLoadWasTamperedOrCorrupt[pn] = false; - m_bLastLoadWasFromLastGood[pn] = false; - m_bNeedToBackUpLastLoad[pn] = false; - m_pMemoryCardProfile[pn]->InitAll(); - SONGMAN->FreeAllLoadedFromProfile( (ProfileSlot) pn ); -} - -const Profile* ProfileManager::GetProfile( PlayerNumber pn ) const -{ - ASSERT( pn >= 0 && pn < NUM_PLAYERS ); - - if( m_sProfileDir[pn].empty() ) - { - // return an empty profile - return m_pMemoryCardProfile[pn]; - } - else if( ProfileWasLoadedFromMemoryCard(pn) ) - { - return m_pMemoryCardProfile[pn]; - } - else - { - RString sProfileID = LocalProfileDirToID( m_sProfileDir[pn] ); - return GetLocalProfile( sProfileID ); - } -} - -RString ProfileManager::GetPlayerName( PlayerNumber pn ) const -{ - const Profile *prof = GetProfile( pn ); - return prof ? prof->GetDisplayNameOrHighScoreName() : RString(); -} - - -void ProfileManager::UnloadAllLocalProfiles() -{ - g_vLocalProfile.clear(); -} - -void ProfileManager::RefreshLocalProfilesFromDisk() -{ - UnloadAllLocalProfiles(); - - vector vsProfileID; - GetDirListing( USER_PROFILES_DIR + "*", vsProfileID, true, true ); - FOREACH_CONST( RString, vsProfileID, p ) - { - g_vLocalProfile.push_back( DirAndProfile() ); - DirAndProfile &dap = g_vLocalProfile.back(); - dap.sDir = *p + "/"; - dap.profile.LoadAllFromDir( dap.sDir, PREFSMAN->m_bSignProfileData ); - } -} - -const Profile *ProfileManager::GetLocalProfile( const RString &sProfileID ) const -{ - RString sDir = LocalProfileIDToDir( sProfileID ); - FOREACH_CONST( DirAndProfile, g_vLocalProfile, dap ) - { - const RString &sOther = dap->sDir; - if( sOther == sDir ) - return &dap->profile; - } - - return NULL; -} - -bool ProfileManager::CreateLocalProfile( RString sName, RString &sProfileIDOut ) -{ - ASSERT( !sName.empty() ); - - // Find a directory directory name that's a number greater than all - // existing numbers. This preserves the "order by create date". - int iMaxProfileNumber = -1; - vector vs; - GetLocalProfileIDs( vs ); - FOREACH_CONST( RString, vs, s ) - iMaxProfileNumber = StringToInt( *s ); - - int iProfileNumber = iMaxProfileNumber + 1; - RString sProfileID = ssprintf( "%08d", iProfileNumber ); - - // Create the new profile. - Profile *pProfile = new Profile; - pProfile->m_sDisplayName = sName; - pProfile->m_sCharacterID = CHARMAN->GetRandomCharacter()->m_sCharacterID; - - // Save it to disk. - RString sProfileDir = LocalProfileIDToDir( sProfileID ); - if( !pProfile->SaveAllToDir(sProfileDir, PREFSMAN->m_bSignProfileData) ) - { - delete pProfile; - sProfileIDOut = ""; - return false; - } - - AddLocalProfileByID( pProfile, sProfileID ); - - sProfileIDOut = sProfileID; - return true; -} - -void ProfileManager::AddLocalProfileByID( Profile *pProfile, RString sProfileID ) -{ - // make sure this id doesn't already exist - ASSERT_M( GetLocalProfile(sProfileID) == NULL, - ssprintf("creating \"%s\" \"%s\" that already exists", - pProfile->m_sDisplayName.c_str(), sProfileID.c_str()) ); - - // insert - g_vLocalProfile.push_back( DirAndProfile() ); - DirAndProfile &dap = g_vLocalProfile.back(); - dap.sDir = LocalProfileIDToDir( sProfileID ); - dap.profile = *pProfile; -} - -bool ProfileManager::RenameLocalProfile( RString sProfileID, RString sNewName ) -{ - ASSERT( !sProfileID.empty() ); - - Profile *pProfile = ProfileManager::GetLocalProfile( sProfileID ); - ASSERT( pProfile ); - pProfile->m_sDisplayName = sNewName; - - RString sProfileDir = LocalProfileIDToDir( sProfileID ); - return pProfile->SaveAllToDir( sProfileDir, PREFSMAN->m_bSignProfileData ); -} - -bool ProfileManager::DeleteLocalProfile( RString sProfileID ) -{ - Profile *pProfile = ProfileManager::GetLocalProfile( sProfileID ); - ASSERT( pProfile ); - RString sProfileDir = LocalProfileIDToDir( sProfileID ); - - // flush directory cache in an attempt to get this working - FILEMAN->FlushDirCache( sProfileDir ); - - FOREACH( DirAndProfile, g_vLocalProfile, i ) - { - if( i->sDir == sProfileDir ) - { - if( DeleteRecursive(sProfileDir) ) - { - g_vLocalProfile.erase( i ); - - // Delete all references to this profileID - FOREACH_CONST( Preference*, m_sDefaultLocalProfileID.m_v, j ) - { - if( (*j)->Get() == sProfileID ) - (*j)->Set( "" ); - } - return true; - } - else - { - LOG->Warn("[ProfileManager::DeleteLocalProfile] DeleteRecursive(%s) failed", - sProfileID.c_str() ); - return false; - } - } - } - - LOG->Warn( "DeleteLocalProfile: ProfileID '%s' doesn't exist", sProfileID.c_str() ); - return false; -} - -void ProfileManager::SaveMachineProfile() const -{ - // If the machine name has changed, make sure we use the new name. - // It's important that this name be applied before the Player profiles - // are saved, so that the Player's profiles show the right machine name. - const_cast (this)->m_pMachineProfile->m_sDisplayName = PREFSMAN->m_sMachineName; - - m_pMachineProfile->SaveAllToDir( MACHINE_PROFILE_DIR, false ); /* don't sign machine profiles */ -} - -void ProfileManager::LoadMachineProfile() -{ - ProfileLoadResult lr = m_pMachineProfile->LoadAllFromDir(MACHINE_PROFILE_DIR, false); - if( lr == ProfileLoadResult_FailedNoProfile ) - { - m_pMachineProfile->InitAll(); - m_pMachineProfile->SaveAllToDir( MACHINE_PROFILE_DIR, PREFSMAN->m_bSignProfileData ); - } - - // If the machine name has changed, make sure we use the new name - m_pMachineProfile->m_sDisplayName = PREFSMAN->m_sMachineName; - - LoadMachineProfileEdits(); -} - -void ProfileManager::LoadMachineProfileEdits() -{ - SONGMAN->FreeAllLoadedFromProfile( ProfileSlot_Machine ); - SONGMAN->LoadStepEditsFromProfileDir( MACHINE_PROFILE_DIR, ProfileSlot_Machine ); - SONGMAN->LoadCourseEditsFromProfileDir( MACHINE_PROFILE_DIR, ProfileSlot_Machine ); -} - -bool ProfileManager::ProfileWasLoadedFromMemoryCard( PlayerNumber pn ) const -{ - return !m_sProfileDir[pn].empty() && m_bWasLoadedFromMemoryCard[pn]; -} - -bool ProfileManager::ProfileFromMemoryCardIsNew( PlayerNumber pn ) const -{ - return GetProfile(pn) && m_bWasLoadedFromMemoryCard[pn] && m_bNewProfile[pn]; -} - -bool ProfileManager::LastLoadWasTamperedOrCorrupt( PlayerNumber pn ) const -{ - return !m_sProfileDir[pn].empty() && m_bLastLoadWasTamperedOrCorrupt[pn]; -} - -bool ProfileManager::LastLoadWasFromLastGood( PlayerNumber pn ) const -{ - return !m_sProfileDir[pn].empty() && m_bLastLoadWasFromLastGood[pn]; -} - -const RString& ProfileManager::GetProfileDir( ProfileSlot slot ) const -{ - switch( slot ) - { - case ProfileSlot_Player1: - case ProfileSlot_Player2: - return m_sProfileDir[slot]; - case ProfileSlot_Machine: - return MACHINE_PROFILE_DIR; - default: - ASSERT(0); - } -} - -RString ProfileManager::GetProfileDirImportedFrom( ProfileSlot slot ) const -{ - switch( slot ) - { - case ProfileSlot_Player1: - case ProfileSlot_Player2: - return m_sProfileDirImportedFrom[slot]; - case ProfileSlot_Machine: - return RString(); - default: - ASSERT(0); - } -} - -const Profile* ProfileManager::GetProfile( ProfileSlot slot ) const -{ - switch( slot ) - { - case ProfileSlot_Player1: - case ProfileSlot_Player2: - return GetProfile( (PlayerNumber)slot ); - case ProfileSlot_Machine: - return m_pMachineProfile; - default: - ASSERT(0); - } -} - -// -// General -// -void ProfileManager::IncrementToastiesCount( PlayerNumber pn ) -{ - if( IsPersistentProfile(pn) ) - ++GetProfile(pn)->m_iNumToasties; - ++GetMachineProfile()->m_iNumToasties; -} - -void ProfileManager::AddStepTotals( PlayerNumber pn, int iNumTapsAndHolds, int iNumJumps, int iNumHolds, int iNumRolls, int iNumMines, int iNumHands, int iNumLifts, float fCaloriesBurned ) -{ - if( IsPersistentProfile(pn) ) - GetProfile(pn)->AddStepTotals( iNumTapsAndHolds, iNumJumps, iNumHolds, iNumRolls, iNumMines, iNumHands, iNumLifts, fCaloriesBurned ); - GetMachineProfile()->AddStepTotals( iNumTapsAndHolds, iNumJumps, iNumHolds, iNumRolls, iNumMines, iNumHands, iNumLifts, fCaloriesBurned ); -} - -// -// Song stats -// -int ProfileManager::GetSongNumTimesPlayed( const Song* pSong, ProfileSlot slot ) const -{ - return GetProfile(slot)->GetSongNumTimesPlayed( pSong ); -} - -void ProfileManager::AddStepsScore( const Song* pSong, const Steps* pSteps, PlayerNumber pn, const HighScore &hs_, int &iPersonalIndexOut, int &iMachineIndexOut ) -{ - HighScore hs = hs_; - hs.SetPercentDP( max(0, hs.GetPercentDP()) ); // bump up negative scores - - iPersonalIndexOut = -1; - iMachineIndexOut = -1; - - // In event mode, set the score's name immediately to the Profile's last - // used name. If no profile last used name exists, use "EVNT". - if( GAMESTATE->IsEventMode() ) - { - Profile* pProfile = GetProfile(pn); - if( pProfile && !pProfile->m_sLastUsedHighScoreName.empty() ) - hs.SetName( pProfile->m_sLastUsedHighScoreName ); - else - hs.SetName( "EVNT" ); - } - else - { - hs.SetName( RANKING_TO_FILL_IN_MARKER[pn] ); - } - - // - // save high score - // - if( IsPersistentProfile(pn) ) - GetProfile(pn)->AddStepsHighScore( pSong, pSteps, hs, iPersonalIndexOut ); - - // don't save machine scores for a failed song - if( hs.GetPercentDP() >= PREFSMAN->m_fMinPercentageForMachineSongHighScore && - hs.GetGrade() != Grade_Failed ) - { - // don't leave machine high scores for edits loaded from the player's card - if( !pSteps->IsAPlayerEdit() ) - GetMachineProfile()->AddStepsHighScore( pSong, pSteps, hs, iMachineIndexOut ); - } - - /* - // save recent score - if( IsPersistentProfile(pn) ) - GetProfile(pn)->SaveStepsRecentScore( pSong, pSteps, hs ); - GetMachineProfile()->SaveStepsRecentScore( pSong, pSteps, hs ); - */ -} - -void ProfileManager::IncrementStepsPlayCount( const Song* pSong, const Steps* pSteps, PlayerNumber pn ) -{ - if( IsPersistentProfile(pn) ) - GetProfile(pn)->IncrementStepsPlayCount( pSong, pSteps ); - GetMachineProfile()->IncrementStepsPlayCount( pSong, pSteps ); -} - -// Course stats -void ProfileManager::AddCourseScore( const Course* pCourse, const Trail* pTrail, PlayerNumber pn, const HighScore &hs_, int &iPersonalIndexOut, int &iMachineIndexOut ) -{ - HighScore hs = hs_; - hs.SetPercentDP(max( 0, hs.GetPercentDP()) ); // bump up negative scores - - iPersonalIndexOut = -1; - iMachineIndexOut = -1; - - // In event mode, set the score's name immediately to the Profile's last - // used name. If no profile last used name exists, use "EVNT". - if( GAMESTATE->IsEventMode() ) - { - Profile* pProfile = GetProfile(pn); - if( pProfile && !pProfile->m_sLastUsedHighScoreName.empty() ) - hs.SetName( pProfile->m_sLastUsedHighScoreName ); - else - hs.SetName( "EVNT" ); - } - else - { - hs.SetName( RANKING_TO_FILL_IN_MARKER[pn] ); - } - - // save high score - if( IsPersistentProfile(pn) ) - GetProfile(pn)->AddCourseHighScore( pCourse, pTrail, hs, iPersonalIndexOut ); - if( hs.GetPercentDP() >= PREFSMAN->m_fMinPercentageForMachineCourseHighScore ) - GetMachineProfile()->AddCourseHighScore( pCourse, pTrail, hs, iMachineIndexOut ); - - /* - // save recent score - if( IsPersistentProfile(pn) ) - GetProfile(pn)->SaveCourseRecentScore( pCourse, pTrail, hs ); - GetMachineProfile()->SaveCourseRecentScore( pCourse, pTrail, hs ); - */ -} - -void ProfileManager::IncrementCoursePlayCount( const Course* pCourse, const Trail* pTrail, PlayerNumber pn ) -{ - if( IsPersistentProfile(pn) ) - GetProfile(pn)->IncrementCoursePlayCount( pCourse, pTrail ); - GetMachineProfile()->IncrementCoursePlayCount( pCourse, pTrail ); -} - -// Category stats -void ProfileManager::AddCategoryScore( StepsType st, RankingCategory rc, PlayerNumber pn, const HighScore &hs_, int &iPersonalIndexOut, int &iMachineIndexOut ) -{ - HighScore hs = hs_; - hs.SetName( RANKING_TO_FILL_IN_MARKER[pn] ); - if( IsPersistentProfile(pn) ) - GetProfile(pn)->AddCategoryHighScore( st, rc, hs, iPersonalIndexOut ); - if( hs.GetPercentDP() > PREFSMAN->m_fMinPercentageForMachineSongHighScore ) - GetMachineProfile()->AddCategoryHighScore( st, rc, hs, iMachineIndexOut ); -} - -void ProfileManager::IncrementCategoryPlayCount( StepsType st, RankingCategory rc, PlayerNumber pn ) -{ - if( IsPersistentProfile(pn) ) - GetProfile(pn)->IncrementCategoryPlayCount( st, rc ); - GetMachineProfile()->IncrementCategoryPlayCount( st, rc ); -} - -bool ProfileManager::IsPersistentProfile( ProfileSlot slot ) const -{ - switch( slot ) - { - case ProfileSlot_Player1: - case ProfileSlot_Player2: - return GAMESTATE->IsHumanPlayer((PlayerNumber)slot) && !m_sProfileDir[slot].empty(); - case ProfileSlot_Machine: - return true; - default: - ASSERT(0); - return false; - } -} - -void ProfileManager::GetLocalProfileIDs( vector &vsProfileIDsOut ) const -{ - vsProfileIDsOut.clear(); - FOREACH_CONST( DirAndProfile, g_vLocalProfile, i) - { - RString sID = LocalProfileDirToID( i->sDir ); - vsProfileIDsOut.push_back( sID ); - } -} - -void ProfileManager::GetLocalProfileDisplayNames( vector &vsProfileDisplayNamesOut ) const -{ - vsProfileDisplayNamesOut.clear(); - FOREACH_CONST( DirAndProfile, g_vLocalProfile, i) - vsProfileDisplayNamesOut.push_back( i->profile.m_sDisplayName ); -} - -int ProfileManager::GetLocalProfileIndexFromID( RString sProfileID ) const -{ - RString sDir = LocalProfileIDToDir( sProfileID ); - FOREACH_CONST( DirAndProfile, g_vLocalProfile, i ) - { - if( i->sDir == sDir ) - return i - g_vLocalProfile.begin(); - } - return -1; -} - -RString ProfileManager::GetLocalProfileIDFromIndex( int iIndex ) -{ - RString sID = LocalProfileDirToID( g_vLocalProfile[iIndex].sDir ); - return sID; -} - -Profile *ProfileManager::GetLocalProfileFromIndex( int iIndex ) -{ - return &g_vLocalProfile[iIndex].profile; -} - -int ProfileManager::GetNumLocalProfiles() const -{ - return g_vLocalProfile.size(); -} - -// lua start -#include "LuaBinding.h" - -/** @brief Allow Lua to have access to the ProfileManager. */ -class LunaProfileManager: public Luna -{ -public: - static int IsPersistentProfile( T* p, lua_State *L ) { lua_pushboolean(L, p->IsPersistentProfile(Enum::Check(L, 1)) ); return 1; } - static int GetProfile( T* p, lua_State *L ) { PlayerNumber pn = Enum::Check(L, 1); Profile* pP = p->GetProfile(pn); ASSERT(pP); pP->PushSelf(L); return 1; } - static int GetMachineProfile( T* p, lua_State *L ) { p->GetMachineProfile()->PushSelf(L); return 1; } - static int SaveMachineProfile( T* p, lua_State *L ) { p->SaveMachineProfile(); return 0; } - static int GetLocalProfile( T* p, lua_State *L ) - { - Profile *pProfile = p->GetLocalProfile(SArg(1)); - if( pProfile ) - pProfile->PushSelf(L); - else - lua_pushnil(L); - return 1; - } - static int GetLocalProfileFromIndex( T* p, lua_State *L ) { Profile *pProfile = p->GetLocalProfileFromIndex(IArg(1)); ASSERT(pProfile); pProfile->PushSelf(L); return 1; } - static int GetLocalProfileIDFromIndex( T* p, lua_State *L ) { lua_pushstring(L, p->GetLocalProfileIDFromIndex(IArg(1)) ); return 1; } - static int GetLocalProfileIndexFromID( T* p, lua_State *L ) { lua_pushnumber(L, p->GetLocalProfileIndexFromID(SArg(1)) ); return 1; } - static int GetNumLocalProfiles( T* p, lua_State *L ) { lua_pushnumber(L, p->GetNumLocalProfiles() ); return 1; } - static int GetProfileDir( T* p, lua_State *L ) { lua_pushstring(L, p->GetProfileDir(Enum::Check(L, 1)) ); return 1; } - static int IsSongNew( T* p, lua_State *L ) { lua_pushboolean(L, p->IsSongNew(Luna::check(L,1)) ); return 1; } - static int ProfileWasLoadedFromMemoryCard( T* p, lua_State *L ) { lua_pushboolean(L, p->ProfileWasLoadedFromMemoryCard(Enum::Check(L, 1)) ); return 1; } - static int LastLoadWasTamperedOrCorrupt( T* p, lua_State *L ) { lua_pushboolean(L, p->LastLoadWasTamperedOrCorrupt(Enum::Check(L, 1)) ); return 1; } - - LunaProfileManager() - { - ADD_METHOD( IsPersistentProfile ); - ADD_METHOD( GetProfile ); - ADD_METHOD( GetMachineProfile ); - ADD_METHOD( SaveMachineProfile ); - ADD_METHOD( GetLocalProfile ); - ADD_METHOD( GetLocalProfileFromIndex ); - ADD_METHOD( GetLocalProfileIDFromIndex ); - ADD_METHOD( GetLocalProfileIndexFromID ); - ADD_METHOD( GetNumLocalProfiles ); - ADD_METHOD( GetProfileDir ); - ADD_METHOD( IsSongNew ); - ADD_METHOD( ProfileWasLoadedFromMemoryCard ); - ADD_METHOD( LastLoadWasTamperedOrCorrupt ); - } -}; - -LUA_REGISTER_CLASS( ProfileManager ) -// lua end - -/* - * (c) 2003-2004 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 "ProfileManager.h" +#include "Profile.h" +#include "RageUtil.h" +#include "PrefsManager.h" +#include "RageLog.h" +#include "RageFile.h" +#include "RageFileManager.h" +#include "GameConstantsAndTypes.h" +#include "SongManager.h" +#include "GameState.h" +#include "Song.h" +#include "Steps.h" +#include "Course.h" +#include "GameManager.h" +#include "ProductInfo.h" +#include "RageUtil.h" +#include "ThemeManager.h" +#include "MemoryCardManager.h" +#include "XmlFile.h" +#include "StepsUtil.h" +#include "Style.h" +#include "HighScore.h" +#include "Character.h" +#include "CharacterManager.h" + + +ProfileManager* PROFILEMAN = NULL; // global and accessable from anywhere in our program + +static void DefaultLocalProfileIDInit( size_t /*PlayerNumber*/ i, RString &sNameOut, RString &defaultValueOut ) +{ + sNameOut = ssprintf( "DefaultLocalProfileIDP%d", int(i+1) ); + defaultValueOut = ""; +} + +Preference ProfileManager::m_bProfileStepEdits( "ProfileStepEdits", true ); +Preference ProfileManager::m_bProfileCourseEdits( "ProfileCourseEdits", true ); +Preference1D ProfileManager::m_sDefaultLocalProfileID( DefaultLocalProfileIDInit, NUM_PLAYERS ); + +const RString NEW_MEM_CARD_NAME = ""; +const RString USER_PROFILES_DIR = "/Save/LocalProfiles/"; +const RString MACHINE_PROFILE_DIR = "/Save/MachineProfile/"; +const RString LAST_GOOD_SUBDIR = "LastGood/"; + + +// Directories to search for a profile if m_sMemoryCardProfileSubdir doesn't +// exist, separated by ";": +static Preference g_sMemoryCardProfileImportSubdirs( "MemoryCardProfileImportSubdirs", "" ); + +static RString LocalProfileIDToDir( const RString &sProfileID ) { return USER_PROFILES_DIR + sProfileID + "/"; } +static RString LocalProfileDirToID( const RString &sDir ) { return Basename( sDir ); } + +struct DirAndProfile +{ + RString sDir; + Profile profile; +}; +static vector g_vLocalProfile; + + +static ThemeMetric FIXED_PROFILES ( "ProfileManager", "FixedProfiles" ); +static ThemeMetric NUM_FIXED_PROFILES ( "ProfileManager", "NumFixedProfiles" ); +#define FIXED_PROFILE_CHARACTER_ID( i ) THEME->GetMetric( "ProfileManager", ssprintf("FixedProfileCharacterID%d",int(i+1)) ) + + +ProfileManager::ProfileManager() +{ + m_pMachineProfile = new Profile; + FOREACH_PlayerNumber(pn) + m_pMemoryCardProfile[pn] = new Profile; + + // Register with Lua. + { + Lua *L = LUA->Get(); + lua_pushstring( L, "PROFILEMAN" ); + this->PushSelf( L ); + lua_settable( L, LUA_GLOBALSINDEX ); + LUA->Release( L ); + } +} + +ProfileManager::~ProfileManager() +{ + // Unregister with Lua. + LUA->UnsetGlobal( "PROFILEMAN" ); + + SAFE_DELETE( m_pMachineProfile ); + FOREACH_PlayerNumber(pn) + SAFE_DELETE( m_pMemoryCardProfile[pn] ); +} + +void ProfileManager::Init() +{ + FOREACH_PlayerNumber( p ) + { + m_bWasLoadedFromMemoryCard[p] = false; + m_bLastLoadWasTamperedOrCorrupt[p] = false; + m_bLastLoadWasFromLastGood[p] = false; + m_bNeedToBackUpLastLoad[p] = false; + m_bNewProfile[p] = false; + } + + LoadMachineProfile(); + + RefreshLocalProfilesFromDisk(); + + if( FIXED_PROFILES ) + { + // resize to the fixed number + if( (int)g_vLocalProfile.size() > NUM_FIXED_PROFILES ) + g_vLocalProfile.erase( g_vLocalProfile.begin()+NUM_FIXED_PROFILES, g_vLocalProfile.end() ); + + for( int i=g_vLocalProfile.size(); iGetCharacterFromID( sCharacterID ); + ASSERT_M( pCharacter, sCharacterID ); + RString sProfileID; + bool b = CreateLocalProfile( pCharacter->GetDisplayName(), sProfileID ); + ASSERT( b ); + Profile* pProfile = GetLocalProfile( sProfileID ); + ASSERT_M( pProfile, sProfileID ); + pProfile->m_sCharacterID = sCharacterID; + SaveLocalProfile( sProfileID ); + } + + ASSERT( (int)g_vLocalProfile.size() == NUM_FIXED_PROFILES ); + } +} + +bool ProfileManager::FixedProfiles() const +{ + return FIXED_PROFILES; +} + +ProfileLoadResult ProfileManager::LoadProfile( PlayerNumber pn, RString sProfileDir, bool bIsMemCard ) +{ + LOG->Trace( "LoadingProfile P%d, %s, %d", pn+1, sProfileDir.c_str(), bIsMemCard ); + + ASSERT( !sProfileDir.empty() ); + ASSERT( sProfileDir.Right(1) == "/" ); + + + m_sProfileDir[pn] = sProfileDir; + m_bWasLoadedFromMemoryCard[pn] = bIsMemCard; + m_bLastLoadWasFromLastGood[pn] = false; + m_bNeedToBackUpLastLoad[pn] = false; + + // Try to load the original, non-backup data. + ProfileLoadResult lr = GetProfile(pn)->LoadAllFromDir( m_sProfileDir[pn], PREFSMAN->m_bSignProfileData ); + + RString sBackupDir = m_sProfileDir[pn] + LAST_GOOD_SUBDIR; + + if( lr == ProfileLoadResult_Success ) + { + /* Next time the profile is written, move this good profile into LastGood. */ + m_bNeedToBackUpLastLoad[pn] = true; + } + + m_bLastLoadWasTamperedOrCorrupt[pn] = lr == ProfileLoadResult_FailedTampered; + + // + // Try to load from the backup if the original data fails to load + // + if( lr == ProfileLoadResult_FailedTampered ) + { + lr = GetProfile(pn)->LoadAllFromDir( sBackupDir, PREFSMAN->m_bSignProfileData ); + m_bLastLoadWasFromLastGood[pn] = lr == ProfileLoadResult_Success; + + /* If the LastGood profile doesn't exist at all, and the actual profile was failed_tampered, + * then the error should be failed_tampered and not failed_no_profile. */ + if( lr == ProfileLoadResult_FailedNoProfile ) + { + LOG->Trace( "Profile was corrupt and LastGood for %s doesn't exist; error is ProfileLoadResult_FailedTampered", + sProfileDir.c_str() ); + lr = ProfileLoadResult_FailedTampered; + } + } + + LOG->Trace( "Done loading profile - result %d", lr ); + + return lr; +} + +bool ProfileManager::LoadLocalProfileFromMachine( PlayerNumber pn ) +{ + RString sProfileID = m_sDefaultLocalProfileID[pn]; + if( sProfileID.empty() ) + { + m_sProfileDir[pn] = ""; + return false; + } + + m_sProfileDir[pn] = LocalProfileIDToDir( sProfileID ); + m_bWasLoadedFromMemoryCard[pn] = false; + m_bLastLoadWasFromLastGood[pn] = false; + + if( GetLocalProfile(sProfileID) == NULL ) + { + m_sProfileDir[pn] = ""; + return false; + } + + return true; +} + +void ProfileManager::GetMemoryCardProfileDirectoriesToTry( vector &asDirsToTry ) +{ + /* Try to load the preferred profile. */ + asDirsToTry.push_back( PREFSMAN->m_sMemoryCardProfileSubdir ); + + /* If that failed, try loading from all fallback directories. */ + split( g_sMemoryCardProfileImportSubdirs, ";", asDirsToTry, true ); +} + +bool ProfileManager::LoadProfileFromMemoryCard( PlayerNumber pn, bool bLoadEdits ) +{ + UnloadProfile( pn ); + + // mount slot + if( MEMCARDMAN->GetCardState(pn) != MemoryCardState_Ready ) + return false; + + vector asDirsToTry; + GetMemoryCardProfileDirectoriesToTry( asDirsToTry ); + m_bNewProfile[pn] = true; + + for( unsigned i = 0; i < asDirsToTry.size(); ++i ) + { + const RString &sSubdir = asDirsToTry[i]; + RString sDir = MEM_CARD_MOUNT_POINT[pn] + sSubdir + "/"; + + /* If the load fails with ProfileLoadResult_FailedNoProfile, keep searching. However, + * if it fails with failed_tampered, data existed but couldn't be loaded; + * we don't want to mess with it, since it's confusing and may wipe out + * recoverable backup data. The only time we really want to import data + * is on the very first use, when the new profile doesn't exist at all, + * but we also want to import scores in the case where the player created + * a directory for edits before playing, so keep searching if the directory + * exists with exists with no scores. */ + ProfileLoadResult res = LoadProfile( pn, sDir, true ); + if( res == ProfileLoadResult_Success ) + { + m_bNewProfile[pn] = false; + /* If importing, store the directory we imported from, for display purposes. */ + if( i > 0 ) + m_sProfileDirImportedFrom[pn] = asDirsToTry[i]; + break; + } + + if( res == ProfileLoadResult_FailedTampered ) + { + m_bNewProfile[pn] = false; + break; + } + } + + /* If we imported a profile fallback directory, change the memory card + * directory back to the preferred directory: never write over imported + * scores. */ + m_sProfileDir[pn] = MEM_CARD_MOUNT_POINT[pn] + (RString)PREFSMAN->m_sMemoryCardProfileSubdir + "/"; + + /* Load edits from all fallback directories, newest first. */ + if( bLoadEdits ) + { + for( unsigned i = 0; i < asDirsToTry.size(); ++i ) + { + const RString &sSubdir = asDirsToTry[i]; + RString sDir = MEM_CARD_MOUNT_POINT[pn] + sSubdir + "/"; + + if( m_bProfileStepEdits ) + SONGMAN->LoadStepEditsFromProfileDir( sDir, (ProfileSlot) pn ); + if( m_bProfileCourseEdits ) + SONGMAN->LoadCourseEditsFromProfileDir( sDir, (ProfileSlot) pn ); + } + } + + return true; // If a card is inserted, we want to use the memory card to save - even if the Profile load failed. +} + +bool ProfileManager::LoadFirstAvailableProfile( PlayerNumber pn, bool bLoadEdits ) +{ + if( LoadProfileFromMemoryCard(pn, bLoadEdits) ) + return true; + + if( LoadLocalProfileFromMachine(pn) ) + return true; + + return false; +} + + +bool ProfileManager::FastLoadProfileNameFromMemoryCard( RString sRootDir, RString &sName ) const +{ + vector asDirsToTry; + GetMemoryCardProfileDirectoriesToTry( asDirsToTry ); + + for( unsigned i = 0; i < asDirsToTry.size(); ++i ) + { + const RString &sSubdir = asDirsToTry[i]; + RString sDir = sRootDir + sSubdir + "/"; + + Profile profile; + ProfileLoadResult res = profile.LoadEditableDataFromDir( sDir ); + if( res == ProfileLoadResult_Success ) + { + sName = profile.GetDisplayNameOrHighScoreName(); + return true; + } + else if( res != ProfileLoadResult_FailedNoProfile ) + break; + } + + return false; +} + +bool ProfileManager::SaveProfile( PlayerNumber pn ) const +{ + if( m_sProfileDir[pn].empty() ) + return false; + + /* + * If the profile we're writing was loaded from the primary (non-backup) + * data, then we've validated it and know it's good. Before writing our + * new data, move the old, good data to the backup. (Only do this once; + * if we save the profile more than once, we haven't re-validated the + * newly written data.) + */ + if( m_bNeedToBackUpLastLoad[pn] ) + { + m_bNeedToBackUpLastLoad[pn] = false; + RString sBackupDir = m_sProfileDir[pn] + LAST_GOOD_SUBDIR; + Profile::MoveBackupToDir( m_sProfileDir[pn], sBackupDir ); + } + + bool b = GetProfile(pn)->SaveAllToDir( m_sProfileDir[pn], PREFSMAN->m_bSignProfileData ); + + return b; +} + +bool ProfileManager::SaveLocalProfile( RString sProfileID ) +{ + const Profile *pProfile = GetLocalProfile( sProfileID ); + ASSERT( pProfile != NULL ); + RString sDir = LocalProfileIDToDir( sProfileID ); + bool b = pProfile->SaveAllToDir( sDir, PREFSMAN->m_bSignProfileData ); + return b; +} + +void ProfileManager::UnloadProfile( PlayerNumber pn ) +{ + m_sProfileDir[pn] = ""; + m_sProfileDirImportedFrom[pn] = ""; + m_bWasLoadedFromMemoryCard[pn] = false; + m_bLastLoadWasTamperedOrCorrupt[pn] = false; + m_bLastLoadWasFromLastGood[pn] = false; + m_bNeedToBackUpLastLoad[pn] = false; + m_pMemoryCardProfile[pn]->InitAll(); + SONGMAN->FreeAllLoadedFromProfile( (ProfileSlot) pn ); +} + +const Profile* ProfileManager::GetProfile( PlayerNumber pn ) const +{ + ASSERT( pn >= 0 && pn < NUM_PLAYERS ); + + if( m_sProfileDir[pn].empty() ) + { + // return an empty profile + return m_pMemoryCardProfile[pn]; + } + else if( ProfileWasLoadedFromMemoryCard(pn) ) + { + return m_pMemoryCardProfile[pn]; + } + else + { + RString sProfileID = LocalProfileDirToID( m_sProfileDir[pn] ); + return GetLocalProfile( sProfileID ); + } +} + +RString ProfileManager::GetPlayerName( PlayerNumber pn ) const +{ + const Profile *prof = GetProfile( pn ); + return prof ? prof->GetDisplayNameOrHighScoreName() : RString(); +} + + +void ProfileManager::UnloadAllLocalProfiles() +{ + g_vLocalProfile.clear(); +} + +void ProfileManager::RefreshLocalProfilesFromDisk() +{ + UnloadAllLocalProfiles(); + + vector vsProfileID; + GetDirListing( USER_PROFILES_DIR + "*", vsProfileID, true, true ); + FOREACH_CONST( RString, vsProfileID, p ) + { + g_vLocalProfile.push_back( DirAndProfile() ); + DirAndProfile &dap = g_vLocalProfile.back(); + dap.sDir = *p + "/"; + dap.profile.LoadAllFromDir( dap.sDir, PREFSMAN->m_bSignProfileData ); + } +} + +const Profile *ProfileManager::GetLocalProfile( const RString &sProfileID ) const +{ + RString sDir = LocalProfileIDToDir( sProfileID ); + FOREACH_CONST( DirAndProfile, g_vLocalProfile, dap ) + { + const RString &sOther = dap->sDir; + if( sOther == sDir ) + return &dap->profile; + } + + return NULL; +} + +bool ProfileManager::CreateLocalProfile( RString sName, RString &sProfileIDOut ) +{ + ASSERT( !sName.empty() ); + + // Find a directory directory name that's a number greater than all + // existing numbers. This preserves the "order by create date". + int iMaxProfileNumber = -1; + vector vs; + GetLocalProfileIDs( vs ); + FOREACH_CONST( RString, vs, s ) + iMaxProfileNumber = StringToInt( *s ); + + int iProfileNumber = iMaxProfileNumber + 1; + RString sProfileID = ssprintf( "%08d", iProfileNumber ); + + // Create the new profile. + Profile *pProfile = new Profile; + pProfile->m_sDisplayName = sName; + pProfile->m_sCharacterID = CHARMAN->GetRandomCharacter()->m_sCharacterID; + + // Save it to disk. + RString sProfileDir = LocalProfileIDToDir( sProfileID ); + if( !pProfile->SaveAllToDir(sProfileDir, PREFSMAN->m_bSignProfileData) ) + { + delete pProfile; + sProfileIDOut = ""; + return false; + } + + AddLocalProfileByID( pProfile, sProfileID ); + + sProfileIDOut = sProfileID; + return true; +} + +void ProfileManager::AddLocalProfileByID( Profile *pProfile, RString sProfileID ) +{ + // make sure this id doesn't already exist + ASSERT_M( GetLocalProfile(sProfileID) == NULL, + ssprintf("creating \"%s\" \"%s\" that already exists", + pProfile->m_sDisplayName.c_str(), sProfileID.c_str()) ); + + // insert + g_vLocalProfile.push_back( DirAndProfile() ); + DirAndProfile &dap = g_vLocalProfile.back(); + dap.sDir = LocalProfileIDToDir( sProfileID ); + dap.profile = *pProfile; +} + +bool ProfileManager::RenameLocalProfile( RString sProfileID, RString sNewName ) +{ + ASSERT( !sProfileID.empty() ); + + Profile *pProfile = ProfileManager::GetLocalProfile( sProfileID ); + ASSERT( pProfile ); + pProfile->m_sDisplayName = sNewName; + + RString sProfileDir = LocalProfileIDToDir( sProfileID ); + return pProfile->SaveAllToDir( sProfileDir, PREFSMAN->m_bSignProfileData ); +} + +bool ProfileManager::DeleteLocalProfile( RString sProfileID ) +{ + Profile *pProfile = ProfileManager::GetLocalProfile( sProfileID ); + ASSERT( pProfile ); + RString sProfileDir = LocalProfileIDToDir( sProfileID ); + + // flush directory cache in an attempt to get this working + FILEMAN->FlushDirCache( sProfileDir ); + + FOREACH( DirAndProfile, g_vLocalProfile, i ) + { + if( i->sDir == sProfileDir ) + { + if( DeleteRecursive(sProfileDir) ) + { + g_vLocalProfile.erase( i ); + + // Delete all references to this profileID + FOREACH_CONST( Preference*, m_sDefaultLocalProfileID.m_v, j ) + { + if( (*j)->Get() == sProfileID ) + (*j)->Set( "" ); + } + return true; + } + else + { + LOG->Warn("[ProfileManager::DeleteLocalProfile] DeleteRecursive(%s) failed", + sProfileID.c_str() ); + return false; + } + } + } + + LOG->Warn( "DeleteLocalProfile: ProfileID '%s' doesn't exist", sProfileID.c_str() ); + return false; +} + +void ProfileManager::SaveMachineProfile() const +{ + // If the machine name has changed, make sure we use the new name. + // It's important that this name be applied before the Player profiles + // are saved, so that the Player's profiles show the right machine name. + const_cast (this)->m_pMachineProfile->m_sDisplayName = PREFSMAN->m_sMachineName; + + m_pMachineProfile->SaveAllToDir( MACHINE_PROFILE_DIR, false ); /* don't sign machine profiles */ +} + +void ProfileManager::LoadMachineProfile() +{ + ProfileLoadResult lr = m_pMachineProfile->LoadAllFromDir(MACHINE_PROFILE_DIR, false); + if( lr == ProfileLoadResult_FailedNoProfile ) + { + m_pMachineProfile->InitAll(); + m_pMachineProfile->SaveAllToDir( MACHINE_PROFILE_DIR, PREFSMAN->m_bSignProfileData ); + } + + // If the machine name has changed, make sure we use the new name + m_pMachineProfile->m_sDisplayName = PREFSMAN->m_sMachineName; + + LoadMachineProfileEdits(); +} + +void ProfileManager::LoadMachineProfileEdits() +{ + SONGMAN->FreeAllLoadedFromProfile( ProfileSlot_Machine ); + SONGMAN->LoadStepEditsFromProfileDir( MACHINE_PROFILE_DIR, ProfileSlot_Machine ); + SONGMAN->LoadCourseEditsFromProfileDir( MACHINE_PROFILE_DIR, ProfileSlot_Machine ); +} + +bool ProfileManager::ProfileWasLoadedFromMemoryCard( PlayerNumber pn ) const +{ + return !m_sProfileDir[pn].empty() && m_bWasLoadedFromMemoryCard[pn]; +} + +bool ProfileManager::ProfileFromMemoryCardIsNew( PlayerNumber pn ) const +{ + return GetProfile(pn) && m_bWasLoadedFromMemoryCard[pn] && m_bNewProfile[pn]; +} + +bool ProfileManager::LastLoadWasTamperedOrCorrupt( PlayerNumber pn ) const +{ + return !m_sProfileDir[pn].empty() && m_bLastLoadWasTamperedOrCorrupt[pn]; +} + +bool ProfileManager::LastLoadWasFromLastGood( PlayerNumber pn ) const +{ + return !m_sProfileDir[pn].empty() && m_bLastLoadWasFromLastGood[pn]; +} + +const RString& ProfileManager::GetProfileDir( ProfileSlot slot ) const +{ + switch( slot ) + { + case ProfileSlot_Player1: + case ProfileSlot_Player2: + return m_sProfileDir[slot]; + case ProfileSlot_Machine: + return MACHINE_PROFILE_DIR; + default: + ASSERT(0); + } +} + +RString ProfileManager::GetProfileDirImportedFrom( ProfileSlot slot ) const +{ + switch( slot ) + { + case ProfileSlot_Player1: + case ProfileSlot_Player2: + return m_sProfileDirImportedFrom[slot]; + case ProfileSlot_Machine: + return RString(); + default: + ASSERT(0); + } +} + +const Profile* ProfileManager::GetProfile( ProfileSlot slot ) const +{ + switch( slot ) + { + case ProfileSlot_Player1: + case ProfileSlot_Player2: + return GetProfile( (PlayerNumber)slot ); + case ProfileSlot_Machine: + return m_pMachineProfile; + default: + ASSERT(0); + } +} + +// +// General +// +void ProfileManager::IncrementToastiesCount( PlayerNumber pn ) +{ + if( IsPersistentProfile(pn) ) + ++GetProfile(pn)->m_iNumToasties; + ++GetMachineProfile()->m_iNumToasties; +} + +void ProfileManager::AddStepTotals( PlayerNumber pn, int iNumTapsAndHolds, int iNumJumps, int iNumHolds, int iNumRolls, int iNumMines, int iNumHands, int iNumLifts, float fCaloriesBurned ) +{ + if( IsPersistentProfile(pn) ) + GetProfile(pn)->AddStepTotals( iNumTapsAndHolds, iNumJumps, iNumHolds, iNumRolls, iNumMines, iNumHands, iNumLifts, fCaloriesBurned ); + GetMachineProfile()->AddStepTotals( iNumTapsAndHolds, iNumJumps, iNumHolds, iNumRolls, iNumMines, iNumHands, iNumLifts, fCaloriesBurned ); +} + +// +// Song stats +// +int ProfileManager::GetSongNumTimesPlayed( const Song* pSong, ProfileSlot slot ) const +{ + return GetProfile(slot)->GetSongNumTimesPlayed( pSong ); +} + +void ProfileManager::AddStepsScore( const Song* pSong, const Steps* pSteps, PlayerNumber pn, const HighScore &hs_, int &iPersonalIndexOut, int &iMachineIndexOut ) +{ + HighScore hs = hs_; + hs.SetPercentDP( max(0, hs.GetPercentDP()) ); // bump up negative scores + + iPersonalIndexOut = -1; + iMachineIndexOut = -1; + + // In event mode, set the score's name immediately to the Profile's last + // used name. If no profile last used name exists, use "EVNT". + if( GAMESTATE->IsEventMode() ) + { + Profile* pProfile = GetProfile(pn); + if( pProfile && !pProfile->m_sLastUsedHighScoreName.empty() ) + hs.SetName( pProfile->m_sLastUsedHighScoreName ); + else + hs.SetName( "EVNT" ); + } + else + { + hs.SetName( RANKING_TO_FILL_IN_MARKER[pn] ); + } + + // + // save high score + // + if( IsPersistentProfile(pn) ) + GetProfile(pn)->AddStepsHighScore( pSong, pSteps, hs, iPersonalIndexOut ); + + // don't save machine scores for a failed song + if( hs.GetPercentDP() >= PREFSMAN->m_fMinPercentageForMachineSongHighScore && + hs.GetGrade() != Grade_Failed ) + { + // don't leave machine high scores for edits loaded from the player's card + if( !pSteps->IsAPlayerEdit() ) + GetMachineProfile()->AddStepsHighScore( pSong, pSteps, hs, iMachineIndexOut ); + } + + /* + // save recent score + if( IsPersistentProfile(pn) ) + GetProfile(pn)->SaveStepsRecentScore( pSong, pSteps, hs ); + GetMachineProfile()->SaveStepsRecentScore( pSong, pSteps, hs ); + */ +} + +void ProfileManager::IncrementStepsPlayCount( const Song* pSong, const Steps* pSteps, PlayerNumber pn ) +{ + if( IsPersistentProfile(pn) ) + GetProfile(pn)->IncrementStepsPlayCount( pSong, pSteps ); + GetMachineProfile()->IncrementStepsPlayCount( pSong, pSteps ); +} + +// Course stats +void ProfileManager::AddCourseScore( const Course* pCourse, const Trail* pTrail, PlayerNumber pn, const HighScore &hs_, int &iPersonalIndexOut, int &iMachineIndexOut ) +{ + HighScore hs = hs_; + hs.SetPercentDP(max( 0, hs.GetPercentDP()) ); // bump up negative scores + + iPersonalIndexOut = -1; + iMachineIndexOut = -1; + + // In event mode, set the score's name immediately to the Profile's last + // used name. If no profile last used name exists, use "EVNT". + if( GAMESTATE->IsEventMode() ) + { + Profile* pProfile = GetProfile(pn); + if( pProfile && !pProfile->m_sLastUsedHighScoreName.empty() ) + hs.SetName( pProfile->m_sLastUsedHighScoreName ); + else + hs.SetName( "EVNT" ); + } + else + { + hs.SetName( RANKING_TO_FILL_IN_MARKER[pn] ); + } + + // save high score + if( IsPersistentProfile(pn) ) + GetProfile(pn)->AddCourseHighScore( pCourse, pTrail, hs, iPersonalIndexOut ); + if( hs.GetPercentDP() >= PREFSMAN->m_fMinPercentageForMachineCourseHighScore ) + GetMachineProfile()->AddCourseHighScore( pCourse, pTrail, hs, iMachineIndexOut ); + + /* + // save recent score + if( IsPersistentProfile(pn) ) + GetProfile(pn)->SaveCourseRecentScore( pCourse, pTrail, hs ); + GetMachineProfile()->SaveCourseRecentScore( pCourse, pTrail, hs ); + */ +} + +void ProfileManager::IncrementCoursePlayCount( const Course* pCourse, const Trail* pTrail, PlayerNumber pn ) +{ + if( IsPersistentProfile(pn) ) + GetProfile(pn)->IncrementCoursePlayCount( pCourse, pTrail ); + GetMachineProfile()->IncrementCoursePlayCount( pCourse, pTrail ); +} + +// Category stats +void ProfileManager::AddCategoryScore( StepsType st, RankingCategory rc, PlayerNumber pn, const HighScore &hs_, int &iPersonalIndexOut, int &iMachineIndexOut ) +{ + HighScore hs = hs_; + hs.SetName( RANKING_TO_FILL_IN_MARKER[pn] ); + if( IsPersistentProfile(pn) ) + GetProfile(pn)->AddCategoryHighScore( st, rc, hs, iPersonalIndexOut ); + if( hs.GetPercentDP() > PREFSMAN->m_fMinPercentageForMachineSongHighScore ) + GetMachineProfile()->AddCategoryHighScore( st, rc, hs, iMachineIndexOut ); +} + +void ProfileManager::IncrementCategoryPlayCount( StepsType st, RankingCategory rc, PlayerNumber pn ) +{ + if( IsPersistentProfile(pn) ) + GetProfile(pn)->IncrementCategoryPlayCount( st, rc ); + GetMachineProfile()->IncrementCategoryPlayCount( st, rc ); +} + +bool ProfileManager::IsPersistentProfile( ProfileSlot slot ) const +{ + switch( slot ) + { + case ProfileSlot_Player1: + case ProfileSlot_Player2: + return GAMESTATE->IsHumanPlayer((PlayerNumber)slot) && !m_sProfileDir[slot].empty(); + case ProfileSlot_Machine: + return true; + default: + ASSERT(0); + return false; + } +} + +void ProfileManager::GetLocalProfileIDs( vector &vsProfileIDsOut ) const +{ + vsProfileIDsOut.clear(); + FOREACH_CONST( DirAndProfile, g_vLocalProfile, i) + { + RString sID = LocalProfileDirToID( i->sDir ); + vsProfileIDsOut.push_back( sID ); + } +} + +void ProfileManager::GetLocalProfileDisplayNames( vector &vsProfileDisplayNamesOut ) const +{ + vsProfileDisplayNamesOut.clear(); + FOREACH_CONST( DirAndProfile, g_vLocalProfile, i) + vsProfileDisplayNamesOut.push_back( i->profile.m_sDisplayName ); +} + +int ProfileManager::GetLocalProfileIndexFromID( RString sProfileID ) const +{ + RString sDir = LocalProfileIDToDir( sProfileID ); + FOREACH_CONST( DirAndProfile, g_vLocalProfile, i ) + { + if( i->sDir == sDir ) + return i - g_vLocalProfile.begin(); + } + return -1; +} + +RString ProfileManager::GetLocalProfileIDFromIndex( int iIndex ) +{ + RString sID = LocalProfileDirToID( g_vLocalProfile[iIndex].sDir ); + return sID; +} + +Profile *ProfileManager::GetLocalProfileFromIndex( int iIndex ) +{ + return &g_vLocalProfile[iIndex].profile; +} + +int ProfileManager::GetNumLocalProfiles() const +{ + return g_vLocalProfile.size(); +} + +// lua start +#include "LuaBinding.h" + +/** @brief Allow Lua to have access to the ProfileManager. */ +class LunaProfileManager: public Luna +{ +public: + static int IsPersistentProfile( T* p, lua_State *L ) { lua_pushboolean(L, p->IsPersistentProfile(Enum::Check(L, 1)) ); return 1; } + static int GetProfile( T* p, lua_State *L ) { PlayerNumber pn = Enum::Check(L, 1); Profile* pP = p->GetProfile(pn); ASSERT(pP); pP->PushSelf(L); return 1; } + static int GetMachineProfile( T* p, lua_State *L ) { p->GetMachineProfile()->PushSelf(L); return 1; } + static int SaveMachineProfile( T* p, lua_State *L ) { p->SaveMachineProfile(); return 0; } + static int GetLocalProfile( T* p, lua_State *L ) + { + Profile *pProfile = p->GetLocalProfile(SArg(1)); + if( pProfile ) + pProfile->PushSelf(L); + else + lua_pushnil(L); + return 1; + } + static int GetLocalProfileFromIndex( T* p, lua_State *L ) { Profile *pProfile = p->GetLocalProfileFromIndex(IArg(1)); ASSERT(pProfile); pProfile->PushSelf(L); return 1; } + static int GetLocalProfileIDFromIndex( T* p, lua_State *L ) { lua_pushstring(L, p->GetLocalProfileIDFromIndex(IArg(1)) ); return 1; } + static int GetLocalProfileIndexFromID( T* p, lua_State *L ) { lua_pushnumber(L, p->GetLocalProfileIndexFromID(SArg(1)) ); return 1; } + static int GetNumLocalProfiles( T* p, lua_State *L ) { lua_pushnumber(L, p->GetNumLocalProfiles() ); return 1; } + static int GetProfileDir( T* p, lua_State *L ) { lua_pushstring(L, p->GetProfileDir(Enum::Check(L, 1)) ); return 1; } + static int IsSongNew( T* p, lua_State *L ) { lua_pushboolean(L, p->IsSongNew(Luna::check(L,1)) ); return 1; } + static int ProfileWasLoadedFromMemoryCard( T* p, lua_State *L ) { lua_pushboolean(L, p->ProfileWasLoadedFromMemoryCard(Enum::Check(L, 1)) ); return 1; } + static int LastLoadWasTamperedOrCorrupt( T* p, lua_State *L ) { lua_pushboolean(L, p->LastLoadWasTamperedOrCorrupt(Enum::Check(L, 1)) ); return 1; } + static int GetPlayerName( T* p, lua_State *L ) { PlayerNumber pn = Enum::Check(L, 1); lua_pushstring(L, p->GetPlayerName(pn)); return 1; } + + LunaProfileManager() + { + ADD_METHOD( IsPersistentProfile ); + ADD_METHOD( GetProfile ); + ADD_METHOD( GetMachineProfile ); + ADD_METHOD( SaveMachineProfile ); + ADD_METHOD( GetLocalProfile ); + ADD_METHOD( GetLocalProfileFromIndex ); + ADD_METHOD( GetLocalProfileIDFromIndex ); + ADD_METHOD( GetLocalProfileIndexFromID ); + ADD_METHOD( GetNumLocalProfiles ); + ADD_METHOD( GetProfileDir ); + ADD_METHOD( IsSongNew ); + ADD_METHOD( ProfileWasLoadedFromMemoryCard ); + ADD_METHOD( LastLoadWasTamperedOrCorrupt ); + ADD_METHOD( GetPlayerName ); + } +}; + +LUA_REGISTER_CLASS( ProfileManager ) +// lua end + +/* + * (c) 2003-2004 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. + */