diff --git a/stepmania/src/FontCharAliases.cpp b/stepmania/src/FontCharAliases.cpp new file mode 100644 index 0000000000..a6b8874de7 --- /dev/null +++ b/stepmania/src/FontCharAliases.cpp @@ -0,0 +1,317 @@ +#include "global.h" +#include "FontCharAliases.h" +#include "Font.h" +#include "RageUtil.h" +#include "RageLog.h" + +#include + +/* Map from "&foo;" to a UTF-8 string. */ +typedef map aliasmap; +static aliasmap CharAliases; +static map CharAliasRepl; + +/* Editing this file in VC6 will be rather ugly, since it contains a lot of UTF-8. + * Just don't change anything you can't read. :) */ + +/* If we move this to an INI, group these, so we can display them in a help + * page off of the TextEntry screen reasonably. + * + * [Game Kanji] + * kakumei1=革 + * [Game Symbols] + * doublezeta=SPECIAL + * [Hiragana] + * [Katakana] + * [Punctuation] + * + * I'm not sure how to handle internal-use character, like Zz. Whenever we write + * text to disk, we need to write placeholders (&doublezeta;) for them, and never + * Unicode characters, since the codepoint is prone to change. We can't currently + * write &these; to SMs, due to format limitations. + */ + +/* Here's a copy-and-paste for a basic Japanese font page: + + 、。〃〄々〆〇〈〉《》「」『』 +【】〒〓〔〕〖〗〘〙〚〛〜〝〞〟 +〠 +〰〱〲〳〴〵〶〷 + ぁあぃいぅうぇえぉおかがきぎく +ぐけげこごさざしじすずせぜそぞた +だちぢっつづてでとどなにぬねのは +ばぱひびぴふぶぷへべぺほぼぽまみ +むめもゃやゅゆょよらりるれろゎわ +ゐゑをんゔ      ゛゜ゝゞ  + ァアィイゥウェエォオカガキギク +グケゲコゴサザシジスズセゼソゾタ +ダチヂッツヅテデトドナニヌネノハ +バパヒビピフブプヘベペホボポマミ +ムメモャヤュユョヨラリルレロヮワ +ヰヱヲンヴヵヶヷヸヹヺ・ーヽヾ  + +And here's one for a kanji page: + + 一ニ三四五六七八 +九十 +革命祭桜小坂鬼道 +弐神様民謡明日青 +衝動猫毛亜熱帯爆 +弾谷新大見解魔法 +扉夜空才 + + */ + +static void InitCharAliases() +{ + if(!CharAliases.empty()) + return; + + CharAliases["default"] = Font::DEFAULT_GLYPH; /* ? */ + CharAliases["invalid"] = INVALID_CHAR; /* 0xFFFF */ + + /* The comments here are UTF-8; they won't show up in VC6 (use your + * imagination). */ + + /* Hiragana: */ + CharAliases["ha"] = 0x3042; /* あ */ + CharAliases["hi"] = 0x3044; /* い */ + CharAliases["hu"] = 0x3046; /* う */ + CharAliases["he"] = 0x3048; /* え */ + CharAliases["ho"] = 0x304a; /* お */ + CharAliases["hka"] = 0x304b; /* か */ + CharAliases["hki"] = 0x304d; /* き */ + CharAliases["hku"] = 0x304f; /* く */ + CharAliases["hke"] = 0x3051; /* け */ + CharAliases["hko"] = 0x3053; /* こ */ + CharAliases["hga"] = 0x304c; /* が */ + CharAliases["hgi"] = 0x304e; /* ぎ */ + CharAliases["hgu"] = 0x3050; /* ぐ */ + CharAliases["hge"] = 0x3052; /* げ */ + CharAliases["hgo"] = 0x3054; /* ご */ + CharAliases["hza"] = 0x3056; /* ざ */ + CharAliases["hzi"] = 0x3058; /* じ */ + CharAliases["hzu"] = 0x305a; /* ず */ + CharAliases["hze"] = 0x305c; /* ぜ */ + CharAliases["hzo"] = 0x305e; /* ぞ */ + CharAliases["hta"] = 0x305f; /* た */ + CharAliases["hti"] = 0x3061; /* ち */ + CharAliases["htu"] = 0x3064; /* つ */ + CharAliases["hte"] = 0x3066; /* て */ + CharAliases["hto"] = 0x3068; /* と */ + CharAliases["hda"] = 0x3060; /* だ */ + CharAliases["hdi"] = 0x3062; /* ぢ */ + CharAliases["hdu"] = 0x3065; /* づ */ + CharAliases["hde"] = 0x3067; /* で */ + CharAliases["hdo"] = 0x3069; /* ど */ + CharAliases["hna"] = 0x306a; /* な */ + CharAliases["hni"] = 0x306b; /* に */ + CharAliases["hnu"] = 0x306c; /* ぬ */ + CharAliases["hne"] = 0x306d; /* ね */ + CharAliases["hno"] = 0x306e; /* の */ + CharAliases["hha"] = 0x306f; /* は */ + CharAliases["hhi"] = 0x3072; /* ひ */ + CharAliases["hhu"] = 0x3075; /* ふ */ + CharAliases["hhe"] = 0x3078; /* へ */ + CharAliases["hho"] = 0x307b; /* ほ */ + CharAliases["hba"] = 0x3070; /* ば */ + CharAliases["hbi"] = 0x3073; /* び */ + CharAliases["hbu"] = 0x3076; /* ぶ */ + CharAliases["hbe"] = 0x3079; /* べ */ + CharAliases["hbo"] = 0x307c; /* ぼ */ + CharAliases["hpa"] = 0x3071; /* ぱ */ + CharAliases["hpi"] = 0x3074; /* ぴ */ + CharAliases["hpu"] = 0x3077; /* ぷ */ + CharAliases["hpe"] = 0x307a; /* ぺ */ + CharAliases["hpo"] = 0x307d; /* ぽ */ + CharAliases["hma"] = 0x307e; /* ま */ + CharAliases["hmi"] = 0x307f; /* み */ + CharAliases["hmu"] = 0x3080; /* む */ + CharAliases["hme"] = 0x3081; /* め */ + CharAliases["hmo"] = 0x3082; /* も */ + CharAliases["hya"] = 0x3084; /* や */ + CharAliases["hyu"] = 0x3086; /* ゆ */ + CharAliases["hyo"] = 0x3088; /* よ */ + CharAliases["hra"] = 0x3089; /* ら */ + CharAliases["hri"] = 0x308a; /* り */ + CharAliases["hru"] = 0x308b; /* る */ + CharAliases["hre"] = 0x308c; /* れ */ + CharAliases["hro"] = 0x308d; /* ろ */ + CharAliases["hwa"] = 0x308f; /* わ */ + CharAliases["hwi"] = 0x3090; /* ゐ */ + CharAliases["hwe"] = 0x3091; /* ゑ */ + CharAliases["hwo"] = 0x3092; /* を */ + CharAliases["hn"] = 0x3093; /* ん */ + CharAliases["hvu"] = 0x3094; /* ゔ */ + CharAliases["has"] = 0x3041; /* ぁ */ + CharAliases["his"] = 0x3043; /* ぃ */ + CharAliases["hus"] = 0x3045; /* ぅ */ + CharAliases["hes"] = 0x3047; /* ぇ */ + CharAliases["hos"] = 0x3049; /* ぉ */ + CharAliases["hkas"] = 0x3095; /* ゕ */ + CharAliases["hkes"] = 0x3096; /* ゖ */ + CharAliases["hsa"] = 0x3055; /* さ */ + CharAliases["hsi"] = 0x3057; /* し */ + CharAliases["hsu"] = 0x3059; /* す */ + CharAliases["hse"] = 0x305b; /* せ */ + CharAliases["hso"] = 0x305d; /* そ */ + CharAliases["hyas"] = 0x3083; /* ゃ */ + CharAliases["hyus"] = 0x3085; /* ゅ */ + CharAliases["hyos"] = 0x3087; /* ょ */ + CharAliases["hwas"] = 0x308e; /* ゎ */ + + /* Katakana: */ + CharAliases["hq"] = 0x3063; /* っ */ + CharAliases["ka"] = 0x30a2; /* ア */ + CharAliases["ki"] = 0x30a4; /* イ */ + CharAliases["ku"] = 0x30a6; /* ウ */ + CharAliases["ke"] = 0x30a8; /* エ */ + CharAliases["ko"] = 0x30aa; /* オ */ + CharAliases["kka"] = 0x30ab; /* カ */ + CharAliases["kki"] = 0x30ad; /* キ */ + CharAliases["kku"] = 0x30af; /* ク */ + CharAliases["kke"] = 0x30b1; /* ケ */ + CharAliases["kko"] = 0x30b3; /* コ */ + CharAliases["kga"] = 0x30ac; /* ガ */ + CharAliases["kgi"] = 0x30ae; /* ギ */ + CharAliases["kgu"] = 0x30b0; /* グ */ + CharAliases["kge"] = 0x30b2; /* ゲ */ + CharAliases["kgo"] = 0x30b4; /* ゴ */ + CharAliases["kza"] = 0x30b6; /* ザ */ + CharAliases["kzi"] = 0x30b8; /* ジ */ + CharAliases["kji"] = 0x30b8; /* ジ */ /* zi/ji alias */ + CharAliases["kzu"] = 0x30ba; /* ズ */ + CharAliases["kze"] = 0x30bc; /* ゼ */ + CharAliases["kzo"] = 0x30be; /* ゾ */ + CharAliases["kta"] = 0x30bf; /* タ */ + CharAliases["kti"] = 0x30c1; /* チ */ + CharAliases["ktu"] = 0x30c4; /* ツ */ + CharAliases["kte"] = 0x30c6; /* テ */ + CharAliases["kto"] = 0x30c8; /* ト */ + CharAliases["kda"] = 0x30c0; /* ダ */ + CharAliases["kdi"] = 0x30c2; /* ヂ */ + CharAliases["kdu"] = 0x30c5; /* ヅ */ + CharAliases["kde"] = 0x30c7; /* デ */ + CharAliases["kdo"] = 0x30c9; /* ド */ + CharAliases["kna"] = 0x30ca; /* ナ */ + CharAliases["kni"] = 0x30cb; /* ニ */ + CharAliases["knu"] = 0x30cc; /* ヌ */ + CharAliases["kne"] = 0x30cd; /* ネ */ + CharAliases["kno"] = 0x30ce; /* ノ */ + CharAliases["kha"] = 0x30cf; /* ハ */ + CharAliases["khi"] = 0x30d2; /* ヒ */ + CharAliases["khu"] = 0x30d5; /* フ */ + CharAliases["khe"] = 0x30d8; /* ヘ */ + CharAliases["kho"] = 0x30db; /* ホ */ + CharAliases["kba"] = 0x30d0; /* バ */ + CharAliases["kbi"] = 0x30d3; /* ビ */ + CharAliases["kbu"] = 0x30d6; /* ブ */ + CharAliases["kbe"] = 0x30d9; /* ベ */ + CharAliases["kbo"] = 0x30dc; /* ボ */ + CharAliases["kpa"] = 0x30d1; /* パ */ + CharAliases["kpi"] = 0x30d4; /* ピ */ + CharAliases["kpu"] = 0x30d7; /* プ */ + CharAliases["kpe"] = 0x30da; /* ペ */ + CharAliases["kpo"] = 0x30dd; /* ポ */ + CharAliases["kma"] = 0x30de; /* マ */ + CharAliases["kmi"] = 0x30df; /* ミ */ + CharAliases["kmu"] = 0x30e0; /* ム */ + CharAliases["kme"] = 0x30e1; /* メ */ + CharAliases["kmo"] = 0x30e2; /* モ */ + CharAliases["kya"] = 0x30e4; /* ヤ */ + CharAliases["kyu"] = 0x30e6; /* ユ */ + CharAliases["kyo"] = 0x30e8; /* ヨ */ + CharAliases["kra"] = 0x30e9; /* ラ */ + CharAliases["kri"] = 0x30ea; /* リ */ + CharAliases["kru"] = 0x30eb; /* ル */ + CharAliases["kre"] = 0x30ec; /* レ */ + CharAliases["kro"] = 0x30ed; /* ロ */ + CharAliases["kwa"] = 0x30ef; /* ワ */ + CharAliases["kwi"] = 0x30f0; /* ヰ */ + CharAliases["kwe"] = 0x30f1; /* ヱ */ + CharAliases["kwo"] = 0x30f2; /* ヲ */ + CharAliases["kn"] = 0x30f3; /* ン */ + CharAliases["kvu"] = 0x30f4; /* ヴ */ + CharAliases["kas"] = 0x30a1; /* ァ */ + CharAliases["kis"] = 0x30a3; /* ィ */ + CharAliases["kus"] = 0x30a5; /* ゥ */ + CharAliases["kes"] = 0x30a7; /* ェ */ + CharAliases["kos"] = 0x30a9; /* ォ */ + CharAliases["kkas"] = 0x30f5; /* ヵ */ + CharAliases["kkes"] = 0x30f6; /* ヶ */ + CharAliases["ksa"] = 0x30b5; /* サ */ + CharAliases["ksi"] = 0x30b7; /* シ */ + CharAliases["ksu"] = 0x30b9; /* ス */ + CharAliases["kse"] = 0x30bb; /* セ */ + CharAliases["kso"] = 0x30bd; /* ソ */ + CharAliases["kyas"] = 0x30e3; /* ャ */ + CharAliases["kyus"] = 0x30e5; /* ュ */ + CharAliases["kyos"] = 0x30e7; /* ョ */ + CharAliases["kwas"] = 0x30ee; /* ヮ */ + CharAliases["kq"] = 0x30c3; /* ッ */ + + CharAliases["kdot"] = 0x30FB; /* ・ */ + CharAliases["kdash"]= 0x30FC; /* ー */ + + /* Symbols: */ + CharAliases["omega"] = 0x03a9; /* Ω */ + CharAliases["whiteheart"] = 0x2661; /* ♡ */ + CharAliases["blackstar"] = 0x2605; /* ★ */ + CharAliases["whitestar"] = 0x2606; /* ☆ */ + CharAliases["flipped-a"] = 0x2200; /* ∀ */ + CharAliases["squared"] = 0x00b2; /* ² */ + CharAliases["cubed"] = 0x00b3; /* ³ */ + CharAliases["oq"] = 0x201c; /* “ */ + CharAliases["cq"] = 0x201d; /* ” */ + CharAliases["leftarrow"] = 0x2190; /* ← */ + CharAliases["uparrow"] = 0x2191; /* ↑ */ + CharAliases["rightarrow"] = 0x2192; /* → */ + CharAliases["downarrow"] = 0x2193; /* ↓ */ + CharAliases["doublezeta"] = 0xE009; + CharAliases["planet"] = 0xE00A; + + /* These are internal-use glyphs; they don't have real Unicode codepoints. */ + CharAliases["up"] = 0xE000; + CharAliases["down"] = 0xE001; + CharAliases["left"] = 0xE002; + CharAliases["right"] = 0xE003; + CharAliases["menuup"] = 0xE004; + CharAliases["menudown"] = 0xE005; + CharAliases["menuleft"] = 0xE006; + CharAliases["menuright"] = 0xE007; + CharAliases["start"] = 0xE008; + + for(aliasmap::const_iterator i = CharAliases.begin(); i != CharAliases.end(); ++i) + { + CString from = ssprintf("&%s;", i->first.c_str()); + CString to = WcharToUTF8(i->second); + from.MakeUpper(); + CharAliasRepl[from] = to; + } +} + +/* Replace all &markers; and &#NNNN;s with UTF-8. */ +void FontCharAliases::ReplaceMarkers( CString &sText ) +{ + InitCharAliases(); + ReplaceText(sText, CharAliasRepl); + Replace_Unicode_Markers(sText); +} + +/* Replace all &markers; and &#NNNN;s with UTF-8. */ +bool FontCharAliases::GetChar( CString &codepoint, wchar_t &ch ) +{ + InitCharAliases(); + aliasmap::const_iterator i = CharAliases.find(codepoint); + if(i == CharAliases.end()) + return false; + + ch = i->second; + return true; +} + +/* + * Copyright (c) 2003 by the person(s) listed below. All rights reserved. + * + * Glenn Maynard + */ diff --git a/stepmania/src/GameState.cpp b/stepmania/src/GameState.cpp index 33cf81a47c..05eb721baa 100644 --- a/stepmania/src/GameState.cpp +++ b/stepmania/src/GameState.cpp @@ -25,6 +25,7 @@ #include "ModeChoice.h" #include "NoteFieldPositioning.h" #include "Character.h" +#include "UnlockSystem.h" GameState* GAMESTATE = NULL; // global and accessable from anywhere in our program @@ -39,13 +40,15 @@ GameState::GameState() // Reset(); m_pPosition = NULL; + m_pUnlockingSys = new UnlockSystem; ResetLastRanking(); ReloadCharacters(); } GameState::~GameState() { - SAFE_DELETE( m_pPosition ); + delete m_pUnlockingSys; + delete m_pPosition; } void GameState::Reset() diff --git a/stepmania/src/GameState.h b/stepmania/src/GameState.h index 34b5b6cfed..d14c508f19 100644 --- a/stepmania/src/GameState.h +++ b/stepmania/src/GameState.h @@ -18,7 +18,6 @@ #include "Style.h" #include "Grade.h" #include "StageStats.h" -#include "UnlockSystem.h" class Song; class Notes; @@ -28,6 +27,7 @@ class StyleDef; struct ModeChoice; class NoteFieldPositioning; class Character; +class UnlockSystem; class GameState { @@ -43,7 +43,7 @@ public: // // Main state info // - UnlockSystem UnlockingSys; + UnlockSystem *m_pUnlockingSys; Game m_CurGame; Style m_CurStyle; bool m_bPlayersCanJoin; // true if it's not too late for a player to join - this only has an effect on the credits message diff --git a/stepmania/src/MusicWheel.cpp b/stepmania/src/MusicWheel.cpp index 4d83838a8c..d7c1160b12 100644 --- a/stepmania/src/MusicWheel.cpp +++ b/stepmania/src/MusicWheel.cpp @@ -31,6 +31,7 @@ #include "RageTextureManager.h" #include "Banner.h" #include "Notes.h" +#include "UnlockSystem.h" #define FADE_SECONDS THEME->GetMetricF("MusicWheel","FadeSeconds") @@ -315,7 +316,7 @@ void MusicWheel::GetSongList(vector &arraySongs, SongSortOrder so, CStrin continue; if( so==SORT_ROULETTE && !pSong->RouletteDisplayed() ) continue; - if( so==SORT_ROULETTE && GAMESTATE->UnlockingSys.SongIsRoulette( pSong->GetFullTranslitTitle() ) ) + if( so==SORT_ROULETTE && GAMESTATE->m_pUnlockingSys->SongIsRoulette( pSong->GetFullTranslitTitle() ) ) continue; } @@ -327,7 +328,7 @@ void MusicWheel::GetSongList(vector &arraySongs, SongSortOrder so, CStrin // If we're using unlocks, check it here to prevent from being shown if( PREFSMAN->m_bUseUnlockSystem ) { - pSong->m_bIsLocked = GAMESTATE->UnlockingSys.SongIsLocked( pSong->GetFullTranslitTitle() ); + pSong->m_bIsLocked = GAMESTATE->m_pUnlockingSys->SongIsLocked( pSong->GetFullTranslitTitle() ); if( pSong->m_bIsLocked ) { continue; } } arraySongs.push_back( pSong ); diff --git a/stepmania/src/ScreenSelectDifficultyEX.cpp b/stepmania/src/ScreenSelectDifficultyEX.cpp new file mode 100644 index 0000000000..562eb62faf --- /dev/null +++ b/stepmania/src/ScreenSelectDifficultyEX.cpp @@ -0,0 +1,476 @@ +#include "global.h" +/* +----------------------------------------------------------------------------- + Class: ScreenSelectDifficultyEX + + Desc: See header. + + Copyright (c) 2001-2003 by the person(s) listed below. All rights reserved. + Kevin Slaughter +----------------------------------------------------------------------------- +*/ + +#include "AnnouncerManager.h" +#include "GameManager.h" +#include "GameState.h" +#include "ModeChoice.h" +#include "PrefsManager.h" +#include "RageLog.h" +#include "ScreenManager.h" +#include "ScreenSelectDifficultyEX.h" +#include "ThemeManager.h" + + +#define ANIMATE_MODE_SWITCH THEME->GetMetricB("ScreenSelectDifficultyEX","AnimateModeSwitch") +#define ANIMATE_MODE_SWITCH_LOCK_TIME THEME->GetMetricF("ScreenSelectDifficultyEX","AnimateModeSwitchLockTime") +#define ANIMATE_MODE_SWITCH_INFO_OFF_COMMAND THEME->GetMetric("ScreenSelectDifficultyEX","AnimateModeSwitchInfoOFFCommand") +#define ANIMATE_MODE_SWITCH_INFO_ON_COMMAND THEME->GetMetric("ScreenSelectDifficultyEX","AnimateModeSwitchInfoONCommand") +#define ANIMATE_MODE_SWITCH_PICTURE_OFF_COMMAND THEME->GetMetric("ScreenSelectDifficultyEX","AnimateModeSwitchPictureOFFCommand") +#define ANIMATE_MODE_SWITCH_PICTURE_ON_COMMAND THEME->GetMetric("ScreenSelectDifficultyEX","AnimateModeSwitchPictureONCommand") +#define CURSOR_OFFSET_X_FROM_PICTURE( p ) THEME->GetMetricF("ScreenSelectDifficultyEX",ssprintf("CursorP%dOffsetXFromPicture",p+1)) +#define CURSOR_OFFSET_Y_FROM_PICTURE( p ) THEME->GetMetricF("ScreenSelectDifficultyEX",ssprintf("CursorP%dOffsetYFromPicture",p+1)) +#define DIFFICULTYSPRITE_OFF_COMMAND( p ) THEME->GetMetric("ScreenSelectDifficultyEX",ssprintf("DifficultyIcon%dOFFCommand",p+1)) +#define DIFFICULTYSPRITE_ON_COMMAND( p ) THEME->GetMetric("ScreenSelectDifficultyEX",ssprintf("DifficultyIcon%dONCommand",p+1)) +#define DIFFICULTYSPRITE_X( p ) THEME->GetMetricF("ScreenSelectDifficultyEX",ssprintf("DifficultyIcon%dX",p+1)) +#define DIFFICULTYSPRITE_Y( p ) THEME->GetMetricF("ScreenSelectDifficultyEX",ssprintf("DifficultyIcon%dY",p+1)) +#define DIFFICULTYTEXT_COLOR( p ) THEME->GetMetricC("ScreenSelectDifficultyEX",ssprintf("DifficultyText%dCOLOR",p+1)) +#define DIFFICULTYTEXT_OFF_COMMAND( p ) THEME->GetMetric("ScreenSelectDifficultyEX",ssprintf("DifficultyText%dOFFCommand",p+1)) +#define DIFFICULTYTEXT_ON_COMMAND( p ) THEME->GetMetric("ScreenSelectDifficultyEX",ssprintf("DifficultyText%dONCommand",p+1)) +#define DISABLED_COLOR THEME->GetMetricC("ScreenSelectDifficultyEX","DisabledColor") +#define ICONBAR_OFF_COMMAND THEME->GetMetric("ScreenSelectDifficultyEX","IconBarOFFCommand") +#define ICONBAR_ON_COMMAND THEME->GetMetric("ScreenSelectDifficultyEX","IconBarONCommand") +#define INFO_OFF_COMMAND( p ) THEME->GetMetric("ScreenSelectDifficultyEX",ssprintf("InfoP%dOFFCommand",p+1)) +#define INFO_ON_COMMAND( p ) THEME->GetMetric("ScreenSelectDifficultyEX",ssprintf("InfoP%dONCommand",p+1)) +#define INFO_X( p ) THEME->GetMetricF("ScreenSelectDifficultyEX",ssprintf("InfoXP%d",p+1)) +#define INFO_Y( p ) THEME->GetMetricF("ScreenSelectDifficultyEX",ssprintf("InfoYP%d",p+1)) +#define LOCK_INPUT_SECONDS THEME->GetMetricF("ScreenSelectDifficultyEX","LockInputSeconds") +#define PICTURE_OFF_COMMAND( p ) THEME->GetMetric("ScreenSelectDifficultyEX",ssprintf("PictureP%dOFFCommand",p+1)) +#define PICTURE_ON_COMMAND( p ) THEME->GetMetric("ScreenSelectDifficultyEX",ssprintf("PictureP%dONCommand",p+1)) +#define PICTURE_X( p ) THEME->GetMetricF("ScreenSelectDifficultyEX",ssprintf("PictureXP%d",p+1)) +#define PICTURE_Y( p ) THEME->GetMetricF("ScreenSelectDifficultyEX",ssprintf("PictureYP%d",p+1)) +#define SLEEP_AFTER_CHOICE_SECONDS THEME->GetMetricF("ScreenSelectDifficultyEX","SleepAfterChoiceSeconds") +#define SLEEP_AFTER_TWEEN_OFF_SECONDS THEME->GetMetricF("ScreenSelectDifficultyEX","SleepAfterTweenOffSeconds") + + +ScreenSelectDifficultyEX::ScreenSelectDifficultyEX() : ScreenSelect( "ScreenSelectDifficultyEX" ) +{ + m_CurrentPage = PAGE_1; + int p; + for( p=0; pGetPathToG("ScreenSelectDifficultyEX icon bar.png") ); + this->AddChild( &m_sprIconBar ); + + for( unsigned k=0; k < m_NumModes || k <= 7 ; k++ ) + { + CString MOO = m_aModeChoices[k].name; + if( IsValidModeName(MOO) ) + { + // We cannot show more than 8 icons at a time, BTW + m_sprDifficulty[k].Load( THEME->GetPathToG("ScreenSelectDifficultyEX icons 1x10") ); + m_sprDifficulty[k].StopAnimating(); + m_sprDifficulty[k].SetX( DIFFICULTYSPRITE_X(k) ); + m_sprDifficulty[k].SetY( DIFFICULTYSPRITE_Y(k) ); + m_sprDifficulty[k].SetZoom( 1 ); + this->AddChild( &m_sprDifficulty[k] ); + + m_textDifficultyText[k].SetHorizAlign( Actor::align_left ); + m_textDifficultyText[k].LoadFromFont( THEME->GetPathToF("Common normal") ); + m_textDifficultyText[k].SetX( DIFFICULTYSPRITE_X(k) + 20 ); + m_textDifficultyText[k].SetY( DIFFICULTYSPRITE_Y(k) ); + m_textDifficultyText[k].SetZoom( .5 ); + m_textDifficultyText[k].SetShadowLength( 1 ); //No shadow, jus outline + m_textDifficultyText[k].SetDiffuse( DIFFICULTYTEXT_COLOR(k) ); + this->AddChild( &m_textDifficultyText[k] ); + } + } + SetDifficultyIconText( false ); // Make sure we show the names! + + for( p=0; pIsPlayerEnabled(p) ) // Only show their cursor, if they're enabled + { + m_sprHighlight[p].SetHorizAlign( Actor::align_left ); + m_sprHighlight[p].Load( (PlayerNumber)p, false ); + this->AddChild( &m_sprHighlight[p] ); + this->MoveToHead( &m_sprHighlight[p] ); + } + + CLAMP( m_iChoice[p], 0, (int)m_ModeChoices.size()-1 ); + m_bChosen[p] = false; + + if( !GAMESTATE->IsPlayerEnabled((PlayerNumber)p) ) { continue; } + float fCursorX = GetCursorX( (PlayerNumber)p ); + float fCursorY = GetCursorY( (PlayerNumber)p ); + + CString sInfoFile = ssprintf( "ScreenSelectDifficultyEX info %s", m_ModeChoices[0].name ); + CString sPictureFile = ssprintf( "ScreenSelectDifficultyEX picture %s", m_ModeChoices[0].name ); + + m_sprPicture[p].Load( THEME->GetPathToG(sPictureFile) ); + m_sprPicture[p].SetXY( PICTURE_X(p), PICTURE_Y(p) ); + m_framePages.AddChild( &m_sprPicture[p] ); + + m_sprInfo[p].Load( THEME->GetPathToG(sInfoFile) ); + m_sprInfo[p].SetXY( INFO_X(p), INFO_Y(p) ); + m_framePages.AddChild( &m_sprInfo[p] ); + + m_sprCursor[p].Load( THEME->GetPathToG( "ScreenSelectDifficultyEX cursor 2x1") ); + m_sprCursor[p].SetZoom( 0 ); + m_sprCursor[p].StopAnimating(); + m_sprCursor[p].SetState( p ); + m_sprCursor[p].SetXY( fCursorX, fCursorY ); + m_framePages.AddChild( &m_sprCursor[p] ); + + m_sprOK[p].Load( THEME->GetPathToG( "ScreenSelectDifficultyEX ok 2x1") ); + m_sprOK[p].SetState( p ); + m_sprOK[p].StopAnimating(); + m_sprOK[p].SetDiffuse( RageColor(1,1,1,1) ); + m_sprOK[p].SetXY( fCursorX, fCursorY ); + m_framePages.AddChild( &m_sprOK[p] ); + } + + this->AddChild( &m_framePages ); + m_soundChange.Load( THEME->GetPathToS( "ScreenSelectDifficulty change") ); + m_soundSelect.Load( THEME->GetPathToS( "Common start") ); + m_soundDifficult.Load( ANNOUNCER->GetPathTo("select difficulty challenge") ); + m_fLockInputTime = LOCK_INPUT_SECONDS; + TweenOnScreen(); + + SetAllPlayersSelection( 0, false ); +} + +void ScreenSelectDifficultyEX::Update( float fDelta ) +{ + ScreenSelect::Update( fDelta ); + m_fLockInputTime = max( 0, m_fLockInputTime-fDelta ); +} + +void ScreenSelectDifficultyEX::HandleScreenMessage( const ScreenMessage SM ) +{ + ScreenSelect::HandleScreenMessage( SM ); + + switch( SM ) + { + case SM_BeginFadingOut: + TweenOffScreen(); + SCREENMAN->PostMessageToTopScreen( SM_AllDoneChoosing, SLEEP_AFTER_TWEEN_OFF_SECONDS ); // nofify parent that we're finished + m_Menu.m_MenuTimer.Stop(); + break; + } +} + +int ScreenSelectDifficultyEX::GetSelectionIndex( PlayerNumber pn ) +{ + int index = 0; + for( int page=0; pageIsPlayable(m_ModeChoices[i]) ) + { + m_sprInfo[p].SetDiffuse( RageColor(1,1,1,1) ); + m_sprPicture[p].SetDiffuse( RageColor(1,1,1,1) ); + } + else + { + m_sprInfo[p].SetDiffuse( DISABLED_COLOR ); + m_sprPicture[p].SetDiffuse( DISABLED_COLOR ); + } + } + } + + for( int pa=0; paIsPlayerEnabled(pa) ) + { + MenuRight( (PlayerNumber)pa ); + MenuLeft( (PlayerNumber)pa ); + } +} + +void ScreenSelectDifficultyEX::MenuLeft( PlayerNumber pn ) +{ + if( m_fLockInputTime > 0 ) { return; } + if( m_bChosen[pn] ) { return; } + if( m_iChoice[pn] == 0 ) { return; } + else { Change( pn, m_iChoice[pn]-1 ); } +} + + +void ScreenSelectDifficultyEX::MenuRight( PlayerNumber pn ) +{ + if( m_fLockInputTime > 0 ) { return; } + if( m_bChosen[pn] ) { return; } + if( m_iChoice[pn] < (int)m_ModeChoices.size()-1 ) { Change( pn, m_iChoice[pn]+1 ); } +} + +bool ScreenSelectDifficultyEX::IsACourse( int mIndex ) +{ + CString MODECHOICENAME = m_ModeChoices[mIndex].name; + if( MODECHOICENAME.Left(7) != "arcade-" ) { return true; } + else { return false; } +} + +void ScreenSelectDifficultyEX::SetAllPlayersSelection( int iChoice, bool bSwitchingModes ) +{ + for( int p=0; pGetPathToG(sInfoFile) ); + m_sprPicture[p].Load( THEME->GetPathToG(sPictureFile) ); + + int iDiffIndex = GetSelectionIndex((PlayerNumber)p); + m_sprHighlight[p].SetBarWidth( int(20 + m_sprDifficulty[iDiffIndex].GetZoomedWidth() + (m_textDifficultyText[iDiffIndex].GetWidestLineWidthInSourcePixels() / 2)) ); + m_sprHighlight[p].SetXY( DIFFICULTYSPRITE_X(m_iChoice[p]) + 35, DIFFICULTYSPRITE_Y(m_iChoice[p]) ); + } + + m_soundChange.Play(); +} + +void ScreenSelectDifficultyEX::Change( PlayerNumber pn, int iNewChoice ) +{ + for( int p=0; pIsPlayerEnabled(p) ) { continue; } + if( p!=pn && m_CurrentPage==PAGE_1 ) { continue; } + + // If one player has already chosen, do not allow us to switch between + // Course/Mode & Difficulty + for( int pl=0; plGetPathToG(sInfoFile) ); + m_sprPicture[p].Load( THEME->GetPathToG(sPictureFile) ); + + int iDiffIndex = GetSelectionIndex((PlayerNumber)p); + m_sprHighlight[p].SetBarWidth( int( 20 + m_sprDifficulty[iDiffIndex].GetZoomedWidth() + (m_textDifficultyText[iDiffIndex].GetWidestLineWidthInSourcePixels() /2 )) ); + m_sprHighlight[p].SetXY( DIFFICULTYSPRITE_X(m_iChoice[p]) + 30, DIFFICULTYSPRITE_Y(m_iChoice[p]) ); + } + + m_soundChange.Play(); +} + +bool ScreenSelectDifficultyEX::IsValidModeName( CString ModeName ) +{ + if( ModeName == "arcade-beginner" || ModeName == "beginner" || ModeName == "arcade-easy" || ModeName == "easy" || ModeName == "arcade-medium" || ModeName == "medium" || ModeName == "arcade-hard" || ModeName == "hard" || ModeName == "nonstop" || ModeName == "oni" || ModeName == "endless" || ModeName == "rave" || ModeName == "battle" ) + { + return true; + } + else { return false; }; +} + +int ScreenSelectDifficultyEX::GetIconIndex( CString DiffName ) +{ + if( DiffName == "arcade-beginner" || DiffName == "beginner" ) { return 0; } + else if( DiffName == "arcade-easy" || DiffName == "easy" ) { return 1; } + else if( DiffName == "arcade-medium" || DiffName == "medium" ) { return 2; } + else if( DiffName == "arcade-hard" || DiffName == "hard" ) { return 3; } + else if( DiffName == "nonstop" ) { return 4; } + else if( DiffName == "oni" || DiffName == "challenge" ) { return 5; } + else if( DiffName == "endless" ) { return 6; } + else if( DiffName == "rave" || DiffName == "battle" ) { return 7; } + else { return 10; }; +} + +void ScreenSelectDifficultyEX::SetDifficultyIconText( bool bDisplayCourseItems ) +{ + for( unsigned k=0; k < m_aModeChoices.size(); k++ ) + { + CString MMNAME = m_ModeChoices[k].name; + MMNAME.Replace( "arcade-", "" ); + m_sprDifficulty[k].SetState( GetIconIndex(MMNAME.c_str()) ); + m_textDifficultyText[k].SetDiffuse( RageColor(1,1,1,1) ); + + /* Grammatically correct names. There has to be a better way to + do this.. Anyone? -- Miryo */ + MMNAME.Replace( "beginner", "Beginner"); + MMNAME.Replace( "easy", "Light" ); + MMNAME.Replace( "medium", "Standard" ); + MMNAME.Replace( "hard", "Heavy" ); + MMNAME.Replace( "nonstop", "Nonstop"); + MMNAME.Replace( "oni", "Oni"); + MMNAME.Replace( "endless", "Endless"); + MMNAME.Replace( "rave", "Rave"); + + m_textDifficultyText[k].SetText( MMNAME.c_str() ); + m_textDifficultyText[k].SetDiffuse( DIFFICULTYTEXT_COLOR(k) ); + } +} + +void ScreenSelectDifficultyEX::MenuStart( PlayerNumber pn ) +{ + if( m_fLockInputTime > 0 ) { return; } + if( m_bChosen[pn] == true ) { return; } + m_bChosen[pn] = true; + const ModeChoice& mc = m_ModeChoices[m_iChoice[pn]]; + bool AnotherPlayerSelected = false; + + int p; + for( p=0; pPlayOnceFromDir( ANNOUNCER->GetPathTo(ssprintf("ScreenSelectDifficulty comment %s",mc.name)) ); + m_soundSelect.Play(); + } + + if( IsACourse( m_iChoice[pn] ) ) + { + // If this is course/mode, choose this for all the other players too + for( p=0; pIsPlayerEnabled((PlayerNumber)p) && m_bChosen[p] == false ) + { + return; + } + } + this->PostScreenMessage( SM_BeginFadingOut, SLEEP_AFTER_CHOICE_SECONDS ); // tell our owner it's time to move on +} + +void ScreenSelectDifficultyEX::TweenOnScreen() +{ + unsigned p; + + for( p=0; pIsPlayerEnabled((PlayerNumber)p) ) { continue; } + +// float fCursorX = GetCursorX( (PlayerNumber)p ); +// float fCursorY = GetCursorY( (PlayerNumber)p ); + + m_sprInfo[p].Command( INFO_ON_COMMAND(p) ); + m_sprPicture[p].Command( PICTURE_ON_COMMAND(p) ); + + m_sprHighlight[p].SetXY( DIFFICULTYSPRITE_X(1) + 30, DIFFICULTYSPRITE_Y(1) ); + m_sprHighlight[p].Command( "diffusealpha,0;linear,0.3;diffusealpha,1" ); + } + + m_sprIconBar.Command( ICONBAR_ON_COMMAND ); + for( unsigned di=0; di < m_aModeChoices.size(); di++ ) + { + m_sprDifficulty[di].Command( DIFFICULTYSPRITE_ON_COMMAND(di) ); + m_textDifficultyText[di].Command( DIFFICULTYTEXT_ON_COMMAND(di) ); + } +} + +void ScreenSelectDifficultyEX::TweenOffScreen() +{ + for( int p=0; pIsPlayerEnabled((PlayerNumber)p) ) { continue; } + + m_sprInfo[p].Command( INFO_OFF_COMMAND(p) ); + m_sprPicture[p].Command( PICTURE_OFF_COMMAND(p) ); + m_sprHighlight[p].SetXY( -600,-600 ); + m_sprOK[p].Command( "linear,0.3;diffusealpha,0" ); + } + + m_sprIconBar.Command( ICONBAR_OFF_COMMAND ); + for( unsigned di=0; di < m_aModeChoices.size(); di++ ) + { + m_sprDifficulty[di].Command( DIFFICULTYSPRITE_OFF_COMMAND(di) ); + m_textDifficultyText[di].Command( DIFFICULTYTEXT_OFF_COMMAND(di) ); + } +} + + +float ScreenSelectDifficultyEX::GetCursorX( PlayerNumber pn ) +{ + return m_sprPicture[pn].GetX(); +} + +float ScreenSelectDifficultyEX::GetCursorY( PlayerNumber pn ) +{ + return m_sprPicture[pn].GetY(); +} diff --git a/stepmania/src/ScreenSelectDifficultyEX.h b/stepmania/src/ScreenSelectDifficultyEX.h new file mode 100644 index 0000000000..7b4ca2b68a --- /dev/null +++ b/stepmania/src/ScreenSelectDifficultyEX.h @@ -0,0 +1,84 @@ +#ifndef ScreenSelectDifficultyEX_H +#define ScreenSelectDifficultyEX_H +/* +----------------------------------------------------------------------------- + Class: ScreenSelectDifficultyEX + + Desc: DDR Extreme Difficulty Select + + Copyright (c) 2001-2003 by the person(s) listed below. All rights reserved. + Kevin Slaughter +----------------------------------------------------------------------------- +*/ + + +#include "BitmapText.h" +#include "RageSound.h" +#include "RandomSample.h" +#include "ScreenSelect.h" +#include "Sprite.h" +#include "DifficultyIcon.h" +#include "OptionsCursor.h" + +class ScreenSelectDifficultyEX : public ScreenSelect +{ +public: + ScreenSelectDifficultyEX(); + + virtual void HandleScreenMessage( const ScreenMessage SM ); + virtual void MenuLeft( PlayerNumber pn ); + virtual void MenuRight( PlayerNumber pn ); + virtual void MenuUp( PlayerNumber pn ) {}; + virtual void MenuDown( PlayerNumber pn ) {}; + virtual void MenuStart( PlayerNumber pn ); + virtual void TweenOffScreen(); + virtual void TweenOnScreen(); + virtual void Update( float fDelta ); + +protected: + enum Page { PAGE_1, NUM_PAGES }; + + virtual int GetSelectionIndex( PlayerNumber pn ); + virtual void UpdateSelectableChoices(); + + void Change( PlayerNumber pn, int iNewChoice ); + float GetCursorX( PlayerNumber pn ); + float GetCursorY( PlayerNumber pn ); + bool IsACourse( int mIndex ); + bool IsValidModeName( CString ModeName ); + void SetAllPlayersSelection( int iChoice, bool bSwitchingModes ); + + ActorFrame m_framePages; + Sprite m_sprCursor[NUM_PLAYERS]; + Sprite m_sprInfo[NUM_PLAYERS]; + + +/* Icon Bar stuff */ + unsigned m_NumModes; + Sprite m_sprDifficulty[8]; + Sprite m_sprIconBar; + BitmapText m_textDifficultyText[8]; + OptionsCursor m_sprHighlight[NUM_PLAYERS]; + + int GetIconIndex( CString DiffName ); + void SetDifficultyIconText( bool bDisplayCourseItems ); +/* -------------- */ + + + Sprite m_sprOK[NUM_PLAYERS]; + Sprite m_sprPicture[NUM_PLAYERS]; + + RageSound m_soundChange; + RageSound m_soundSelect; + RandomSample m_soundDifficult; + + vector m_ModeChoices; + + Page m_CurrentPage; + int m_iChoice[NUM_PLAYERS]; + bool m_bChosen[NUM_PLAYERS]; + + float m_fLockInputTime; +}; + +#endif diff --git a/stepmania/src/ScreenUnlock.cpp b/stepmania/src/ScreenUnlock.cpp new file mode 100644 index 0000000000..a49e7cca7d --- /dev/null +++ b/stepmania/src/ScreenUnlock.cpp @@ -0,0 +1,33 @@ +#include "global.h" +#include "PrefsManager.h" +#include "ScreenUnlock.h" +#include "ThemeManager.h" +#include "GameState.h" +#include "RageLog.h" +#include "UnlockSystem.h" + +ScreenUnlock::ScreenUnlock() : ScreenAttract("ScreenUnlock") +{ + LOG->Trace("ScreenUnlock::ScreenUnlock()"); + PointsUntilNextUnlock.LoadFromFont( THEME->GetPathToF("Common normal") ); + PointsUntilNextUnlock.SetHorizAlign( Actor::align_left ); + + CString sDP = ssprintf( "%f", GAMESTATE->m_pUnlockingSys->NumPointsUntilNextUnlock() ); + + // Remove the decimal + if( sDP.Find(".",1) > 0 ) + { + sDP = sDP.Left(sDP.Find(".",1)); + } + + // No negative numbers + if( sDP.Left(1) == "-" ) + { + sDP = "*"; + }; + + PointsUntilNextUnlock.SetText( sDP ); + PointsUntilNextUnlock.SetZoom( 3 ); + PointsUntilNextUnlock.SetXY( 10, 370 ); + this->AddChild( &PointsUntilNextUnlock ); +} \ No newline at end of file diff --git a/stepmania/src/StepMania.cpp b/stepmania/src/StepMania.cpp index 7f8cce7bbf..2330366c86 100644 --- a/stepmania/src/StepMania.cpp +++ b/stepmania/src/StepMania.cpp @@ -48,6 +48,7 @@ #include "InputQueue.h" #include "SongCacheIndex.h" #include "BannerCache.h" +#include "UnlockSystem.h" /* This is also a global class; we own it. */ ArchHooks *HOOKS = NULL; @@ -533,7 +534,7 @@ int main(int argc, char* argv[]) ResetGame(); /* Load the unlocks into memory */ - GAMESTATE->UnlockingSys.LoadFromDATFile("Data/Unlocks.dat"); + GAMESTATE->m_pUnlockingSys->LoadFromDATFile("Data/Unlocks.dat"); /* Run the main loop. */ GameLoop(); diff --git a/stepmania/src/UnlockSystem.cpp b/stepmania/src/UnlockSystem.cpp new file mode 100644 index 0000000000..a58822c606 --- /dev/null +++ b/stepmania/src/UnlockSystem.cpp @@ -0,0 +1,293 @@ +/* +----------------------------------------------------------------------------- + Class: UnlockSystem + + Desc: See header. + + Copyright (c) 2001-2003 by the person(s) listed below. All rights reserved. + Kevin Slaughter +----------------------------------------------------------------------------- +*/ + +#include "global.h" +#include "PrefsManager.h" +#include "RageLog.h" +#include "RageException.h" +#include "RageUtil.h" +#include "UnlockSystem.h" + +#include +using namespace std; + +#include "stdio.h" + +// #define POINTS_ACCUMULATED_BEFORE_LAST_ROUND // Load from file here + +UnlockSystem::UnlockSystem() +{ +} + + +bool UnlockSystem::SongIsLocked( CString sSongName ) +{ + sSongName.MakeUpper(); //Avoid case-sensitive problems + + for(unsigned i = 0; i < m_SongEntries.size(); i++) + if (m_SongEntries[i].m_sSongName == sSongName) + return m_SongEntries[i].isLocked; + + return false; +} + +bool UnlockSystem::SongIsRoulette( CString sSongName ) +{ + sSongName.MakeUpper(); //Avoid case-sensitive problems + + for(unsigned i = 0; i < m_SongEntries.size(); i++) + if (m_SongEntries[i].m_sSongName == sSongName) + return (m_SongEntries[i].m_iRouletteSeed != 0); + + return false; +} + +operator == (const SongEntry &a, const SongEntry &b) +{ + return a.m_sSongName == b.m_sSongName; +} + +operator != (const SongEntry &a, const SongEntry &b) +{ + return a.m_sSongName != b.m_sSongName; +} + +operator >= (const SongEntry &a, const SongEntry &b) +{ + return a.m_sSongName >= b.m_sSongName; +} + +operator <= (const SongEntry &a, const SongEntry &b) +{ + return a.m_sSongName <= b.m_sSongName; +} + +operator > (const SongEntry &a, const SongEntry &b) +{ + return a.m_sSongName > b.m_sSongName; +} + +operator < (const SongEntry &a, const SongEntry &b) +{ + return a.m_sSongName <= b.m_sSongName; +} + +SongEntry::SongEntry() +{ + m_fDancePointsRequired = 0; + m_fArcadePointsRequired = 0; + m_fSongPointsRequired = 0; + m_fExtraStagesCleared = 0; + m_fExtraStagesFailed = 0; + m_fStagesCleared = 0; + m_fToastysSeen = 0; + m_iRouletteSeed = 0; + + isLocked = true; +} + + +static int CompareSongEntries(const SongEntry &se1, const SongEntry &se2) +{ + return se1.m_sSongName < se2.m_sSongName; +} + +bool UnlockSystem::ParseRow(CString text, CString &type, float &qty, + CString &songname) +{ + int pos = -1; + int end; + char unlock_type[4]; + char qty_text[20]; + + while (text[pos] != '|' && pos < text[pos] != '\0') + { + pos++; + if (text[pos] == '[') text[pos] = ' '; + if (text[pos] == ']') text[pos] = ' ';; + if (text[pos] == '|') + { + end = pos; + text[pos] = ' '; + } + } + + /* XXX: "local variable 'end' may be used without having been initialized"; + * I havn't looked at this code to see if it's a problem, but I don't want + * to simply silence the warning without being sure. (Can this just be + * a standard INI--does it actually need to be another file format?) -glenn */ + songname = text.Right(text.GetLength() - 1 - end); + + sscanf(text, "%s %s|", unlock_type, qty_text); + + type = unlock_type; + qty = (float) atof(qty_text); + + LOG->Trace( "UnlockSystem Entry %s", text.c_str() ); + LOG->Trace( " Title %s", songname.c_str() ); + LOG->Trace( " Type %s", type.c_str() ); + LOG->Trace( " Value %s", qty_text ); + + + return true; +} + +bool SongEntry::updateLocked() +{ + if (!isLocked) return true; // if its already true + + if (m_fArcadePointsRequired != 0) + isLocked = (PREFSMAN->m_fArcadePointsAccumulated < m_fArcadePointsRequired); + + if (m_fDancePointsRequired != 0) + isLocked = (PREFSMAN->m_fDancePointsAccumulated < m_fDancePointsRequired); + + if (m_fSongPointsRequired != 0) + isLocked = (PREFSMAN->m_fSongPointsAccumulated < m_fSongPointsRequired); + + if (m_fExtraStagesCleared != 0) + isLocked = (PREFSMAN->m_fExtraStagesCleared < m_fExtraStagesCleared); + + if (m_fExtraStagesFailed != 0) + isLocked = (PREFSMAN->m_fExtraStagesFailed < m_fExtraStagesFailed); + + if (m_fStagesCleared != 0) + isLocked = (PREFSMAN->m_fTotalStagesCleared < m_fStagesCleared); + + if (m_fToastysSeen != 0) + isLocked = (PREFSMAN->m_fTotalToastysSeen < m_fToastysSeen); + + if (m_iRouletteSeed != 0) + isLocked = (PREFSMAN->m_RouletteSeeds[m_iRouletteSeed] == '0'); + + return !isLocked; +} + +bool UnlockSystem::LoadFromDATFile( CString sPath ) +{ + LOG->Trace( "UnlockSystem::LoadFromDATFile(%s)", sPath.c_str() ); + + ifstream input; + + input.open(sPath); + if(input.fail()) + { + LOG->Warn( "Error opening file '%s' for reading.", sPath.c_str() ); + return false; + } + + char line[256]; + CString unlock_type, song_title; + float datavalue; + +// m_SongEntries.clear(); + + while(input.getline(line, 255)) + { + if(line[0] == '/' && line[1] == '/') //Check for comments + continue; + + /* "[data1] data2". Ignore whitespace at the beginning of the line. */ + if (!ParseRow(line, unlock_type, datavalue, song_title)) + continue; + + SongEntry current; + + song_title.MakeUpper(); //Avoid case-sensitive problems + current.m_sSongName = song_title; + + if (unlock_type == "AP") + { + current.m_fArcadePointsRequired = datavalue; + current.isLocked = (PREFSMAN->m_fArcadePointsAccumulated < datavalue); + } + if (unlock_type == "DP") + { + current.m_fDancePointsRequired = datavalue; + current.isLocked = (PREFSMAN->m_fDancePointsAccumulated < datavalue); + } + if (unlock_type == "SP") + { + current.m_fSongPointsRequired = datavalue; + current.isLocked = (PREFSMAN->m_fSongPointsAccumulated < datavalue); + } + if (unlock_type == "EC") + { + current.m_fExtraStagesCleared = datavalue; + current.isLocked = (PREFSMAN->m_fExtraStagesCleared < datavalue); + } + if (unlock_type == "EF") + { + current.m_fExtraStagesFailed = datavalue; + current.isLocked = (PREFSMAN->m_fExtraStagesFailed < datavalue); + } + if (unlock_type == "CS") + { + current.m_fStagesCleared = datavalue; + current.isLocked = (PREFSMAN->m_fTotalStagesCleared < datavalue); + } + if (unlock_type == "!!") + { + current.m_fToastysSeen = datavalue; + current.isLocked = (PREFSMAN->m_fTotalToastysSeen < datavalue); + } + if (unlock_type == "RO") + { + current.m_iRouletteSeed = (int)datavalue; + current.isLocked = (PREFSMAN->m_fArcadePointsAccumulated < datavalue); + } + + m_SongEntries.push_back(current); + } + // sort list so we can make use of binary searching + sort( m_SongEntries.begin(), m_SongEntries.end(), CompareSongEntries ); + + for(unsigned i=0; i < m_SongEntries.size(); i++) + LOG->Trace( "UnlockSystem entry: %s", m_SongEntries[i].m_sSongName.c_str() ); + + + + return true; +} + +bool SongEntry::SelectableWheel() +{ + return (!isLocked); // cached +} + +bool SongEntry::SelectableRoulette() +{ + if (!isLocked) return true; + + if (m_iRouletteSeed != 0) return true; + return false; +} + +float UnlockSystem::NumPointsUntilNextUnlock() +{ + float fSmallestPoints; + fSmallestPoints = 4000000000; // or an arbitrarily large value + for( unsigned a=0; a<100; a++ ) + { + // old line: if( m_SongEntries[a].m_fDancePointsRequired >= fSmallestPoints ) + // new: it makes sure the number of points to the song is positive, AND it is less than + // the currently smallest one. (cure) + if( m_SongEntries[a].m_fDancePointsRequired < fSmallestPoints && m_SongEntries[a].m_fDancePointsRequired > PREFSMAN->m_fDancePointsAccumulated) + { + fSmallestPoints = m_SongEntries[a].m_fDancePointsRequired; + } + } + + float fResults = (fSmallestPoints - PREFSMAN->m_fDancePointsAccumulated); + return fResults; +} + + diff --git a/stepmania/src/UnlockSystem.h b/stepmania/src/UnlockSystem.h new file mode 100644 index 0000000000..0373b58a0a --- /dev/null +++ b/stepmania/src/UnlockSystem.h @@ -0,0 +1,72 @@ +#ifndef UNLOCK_SYSTEM_H +#define UNLOCK_SYSTEM_H + +#include "Grade.h" + +/* +----------------------------------------------------------------------------- + Class: UnlockSystem + + Desc: See header. + + Copyright (c) 2001-2003 by the person(s) listed below. All rights reserved. + Kevin Slaughter +----------------------------------------------------------------------------- +*/ +enum UnlockTypes { UNLOCK_AP, UNLOCK_DP, UNLOCK_SP, + UNLOCK_EC, UNLOCK_EF, UNLOCK_SC, + UNLOCK_TT, UNLOCK_RO}; + +struct SongEntry +{ + CString m_sSongName; /* Name of the song in the DWI/SM file itself.. This allows + for a lot easier compatibility since a lot of people's + song folders are named differantly, song names tend to + be the same in the file.*/ + float m_fDancePointsRequired; // Amount of Dance Points needed to unlock this song + float m_fArcadePointsRequired; + float m_fSongPointsRequired; + float m_fExtraStagesCleared; + float m_fExtraStagesFailed; + float m_fStagesCleared; + float m_fToastysSeen; + int m_iRouletteSeed; + + bool isLocked; + + SongEntry(); + + bool SelectableWheel(); + bool SelectableRoulette(); + + bool updateLocked(); + +}; + +class UnlockSystem +{ +public: + UnlockSystem(); + float NumPointsUntilNextUnlock(); + bool SongIsLocked( CString sSongName ); + bool SongIsRoulette( CString sSongName ); + bool LoadFromDATFile( CString sPath ); +// bool m_bAllSongsAreUnlocked; // Quick way to check if all songs are unlocked + vector m_SongEntries; // All locked songs are stored here + + float UnlockAddAP(Grade credit); + float UnlockAddDP(float credit); + float UnlockAddSP(Grade credit); + float UnlockClearExtraStage(); + float UnlockFailExtraStage(); + float UnlockClearStage(); + float UnlockToasty(); + bool UnlockRouletteSeed(int seed); + +private: + void SortSongEntriesArray(); + bool ParseRow(CString text, CString &type, float &qty, CString &songname); +}; + + +#endif