From 9f61c9e6ac6b1ac5692cf6352d2ebbd47a31a686 Mon Sep 17 00:00:00 2001 From: claude-bot Date: Mon, 13 Jul 2026 12:27:07 +0000 Subject: Import Cai1Hsu/re3 @ miami (reVC / GTA:VC decompilation) Snapshot import (no upstream history) into git.ancap.in.ua/claude, per @lzcnt. Source: https://github.com/Cai1Hsu/re3 branch miami. --- src/core/Frontend.cpp | 6612 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 6612 insertions(+) create mode 100644 src/core/Frontend.cpp (limited to 'src/core/Frontend.cpp') diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp new file mode 100644 index 0000000..d6c2649 --- /dev/null +++ b/src/core/Frontend.cpp @@ -0,0 +1,6612 @@ +#define FORCE_PC_SCALING +#define WITHWINDOWS +#define WITHDINPUT +#include "common.h" +#ifndef PS2_MENU +#include "crossplatform.h" +#include "platform.h" +#include "Frontend.h" +#include "Font.h" +#include "Pad.h" +#include "Text.h" +#include "main.h" +#include "RwHelper.h" +#include "Timer.h" +#include "Game.h" +#include "DMAudio.h" +#include "FileMgr.h" +#include "Streaming.h" +#include "TxdStore.h" +#include "General.h" +#include "GenericGameStorage.h" +#include "Script.h" +#include "Camera.h" +#include "ControllerConfig.h" +#include "Vehicle.h" +#include "MBlur.h" +#include "PlayerSkin.h" +#include "PlayerInfo.h" +#include "World.h" +#include "Renderer.h" +#include "CdStream.h" +#include "Radar.h" +#include "Stats.h" +#include "Messages.h" +#include "FileLoader.h" +#include "User.h" +#include "sampman.h" + +// Similar story to Hud.cpp: +// Game has colors inlined in code. +// For easier modification we collect them here: +const CRGBA LABEL_COLOR(255, 150, 225, 255); +const CRGBA SELECTIONBORDER_COLOR(25, 130, 70, 255); +const CRGBA MENUOPTION_COLOR = LABEL_COLOR; +const CRGBA SELECTEDMENUOPTION_COLOR = LABEL_COLOR; +const CRGBA HEADER_COLOR = LABEL_COLOR; +const CRGBA DARKMENUOPTION_COLOR(195, 90, 165, 255); +const CRGBA SLIDERON_COLOR(97, 194, 247, 255); +const CRGBA SLIDEROFF_COLOR(27, 89, 130, 255); +const CRGBA LIST_BACKGROUND_COLOR(49, 101, 148, 130); +const CRGBA LIST_OPTION_COLOR(155, 155, 155, 255); +const CRGBA RADIO_SELECTOR_COLOR = SLIDEROFF_COLOR; +const CRGBA INACTIVE_RADIO_COLOR(100, 100, 255, 100); +const CRGBA SCROLLBAR_COLOR = LABEL_COLOR; + +#define MAP_MIN_SIZE 162.f +#define MAP_SIZE_TO_ALLOW_X_MOVE 297.f + +#define MAX_VISIBLE_LIST_ROW 30 +#define SCROLLBAR_MAX_HEIGHT 263.0f // not in end result +#define SCROLLABLE_PAGES + +#define hasNativeList(screen) (screen == MENUPAGE_SKIN_SELECT || screen == MENUPAGE_KEYBOARD_CONTROLS) + +#ifdef SCROLLABLE_PAGES +#define MAX_VISIBLE_OPTION 12 +#define MAX_VISIBLE_OPTION_ON_SCREEN (hasNativeList(m_nCurrScreen) ? MAX_VISIBLE_LIST_ROW : MAX_VISIBLE_OPTION) +#define SCREEN_HAS_AUTO_SCROLLBAR (m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen)) + +int GetOptionCount(int screen) +{ + int i = 0; + for (; i < NUM_MENUROWS && aScreens[screen].m_aEntries[i].m_Action != MENUACTION_NOTHING; i++); + return i; +} + +#define SETUP_SCROLLING(screen) \ + if (!hasNativeList(screen)) { \ + m_nTotalListRow = GetOptionCount(screen); \ + if (m_nTotalListRow > MAX_VISIBLE_OPTION) { \ + m_nSelectedListRow = 0; \ + m_nFirstVisibleRowOnList = 0; \ + m_nScrollbarTopMargin = 0; \ + } \ + } + +#define MINUS_SCROLL_OFFSET - scrollOffset +#else +#define MAX_VISIBLE_OPTION_ON_SCREEN MAX_VISIBLE_LIST_ROW +#define SETUP_SCROLLING(screen) +#define MINUS_SCROLL_OFFSET +#endif + +#ifdef TRIANGLE_BACK_BUTTON +#define GetBackJustUp GetTriangleJustUp +#define GetBackJustDown GetTriangleJustDown +#elif defined(CIRCLE_BACK_BUTTON) +#define GetBackJustUp GetCircleJustUp +#define GetBackJustDown GetCircleJustDown +#else +#define GetBackJustUp GetSquareJustUp +#define GetBackJustDown GetSquareJustDown +#endif + +#ifdef MAP_ENHANCEMENTS +CVector2D mapCrosshair; +#endif + +#ifdef CUTSCENE_BORDERS_SWITCH +bool CMenuManager::m_PrefsCutsceneBorders = true; +#endif + +bool holdingScrollBar; // *(bool*)0x7039B9; // not original name + +CMenuManager FrontEndMenuManager; +MenuTrapezoid menuBg(CGeneral::GetRandomNumber() % 40 + 65, CGeneral::GetRandomNumber() % 40 + 21, + CGeneral::GetRandomNumber() % 40 + 568, CGeneral::GetRandomNumber() % 40 + 44, + CGeneral::GetRandomNumber() % 40 + 36, CGeneral::GetRandomNumber() % 40 + 352, + CGeneral::GetRandomNumber() % 40 + 593, CGeneral::GetRandomNumber() % 40 + 312); + +MenuTrapezoid menuOptionHighlight(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); + +#ifndef MASTER +bool CMenuManager::m_PrefsMarketing = false; +bool CMenuManager::m_PrefsDisableTutorials = false; +#endif // !MASTER + +#ifdef GAMEPAD_MENU +uint32 TimeToStopPadShaking; +#endif + +const char* FrontendFilenames[][2] = { + {"background", ""}, + {"vc_logo", "vc_logom"}, + {"mouse", "mousea"}, + {"mapTop01", "mapTop01A"}, + {"mapTop02", "mapTop02A"}, + {"mapTop03", "mapTop03A"}, + {"mapMid01", "mapMid01A"}, + {"mapMid02", "mapMid02A"}, + {"mapMid03", "mapMid03A"}, + {"mapBot01", "mapBot01A"}, + {"mapBot02", "mapBot02A"}, + {"mapBot03", "mapBot03A"}, + {"wildstyle", "wildstyleA"}, + {"flash", "flashA"}, + {"kchat", "kchatA"}, + {"fever", "feverA"}, + {"vrock", "vrockA"}, + {"vcpr", "vcprA"}, + {"espantoso", "espantosoA"}, + {"emotion", "emotionA"}, + {"wave103", "wave103A"}, + {"mp3", "mp3A"}, + {"downOff", "buttonA"}, + {"downOn", "buttonA"}, + {"upOff", "buttonA"}, + {"upOn", "buttonA"}, +#ifdef GAMEPAD_MENU + {"fe_controller", "" }, + {"fe_arrows1", "" }, + {"fe_arrows2", "" }, + {"fe_arrows3", "" }, + {"fe_arrows4", "" }, +#endif +}; + +#define MENU_X_RIGHT_ALIGNED(x) SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - (x)) + +#ifdef ASPECT_RATIO_SCALE +// All of the defines below replace the StretchX function. Otherwise use SCREEN_SCALE_X. +#define MENU_X_LEFT_ALIGNED(x) SCALE_AND_CENTER_X(x) +#define MENU_X(x) SCREEN_SCALE_X(x) +#define MENU_Y(y) SCREEN_SCALE_Y(y) +#else +#define MENU_X_LEFT_ALIGNED(x) StretchX(x) +#define MENU_X(x) StretchX(x) +#define MENU_Y(y) StretchY(y) +#endif + +#ifdef XBOX_MESSAGE_SCREEN +bool CMenuManager::m_bDialogOpen = false; +uint32 CMenuManager::m_nDialogHideTimer = 0; +PauseModeTime CMenuManager::m_nDialogHideTimerPauseMode = 0; +bool CMenuManager::m_bSaveWasSuccessful = false; +wchar* CMenuManager::m_pDialogText = nil; +#endif + +#define SET_FONT_FOR_MENU_HEADER \ + CFont::SetRightJustifyOn(); \ + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); \ + CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); \ + CFont::SetDropShadowPosition(0); + +#define SET_FONT_FOR_LIST_ITEM \ + CFont::SetRightJustifyOff(); \ + CFont::SetScale(MENU_X(LISTITEM_X_SCALE), MENU_Y(LISTITEM_Y_SCALE)); \ + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + +#define RESET_FONT_FOR_NEW_PAGE \ + CFont::SetBackgroundOff(); \ + CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT)); \ + CFont::SetPropOn(); \ + CFont::SetCentreOff(); \ + CFont::SetJustifyOn(); \ + CFont::SetRightJustifyOff(); \ + CFont::SetBackGroundOnlyTextOn(); \ + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); \ + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN)); + +#define ProcessSlider(value, origY, increaseAction, decreaseAction, hoverEndX, onlyWhenHoveringRow) \ + do { \ + float y = origY MINUS_SCROLL_OFFSET; \ + lastActiveBarX = DisplaySlider(MENU_X_LEFT_ALIGNED(MENUSLIDER_X), MENU_Y(y), MENU_Y(MENUSLIDER_SMALLEST_BAR), MENU_Y(MENUSLIDER_BIGGEST_BAR), MENU_X(MENUSLIDER_UNK), value, MENU_X(3.0f)); \ + if (i != m_nCurrOption || !itemsAreSelectable) \ + break; \ + \ + if (CheckHover(0, lastActiveBarX - MENU_X(3.0f), MENU_Y(y), MENU_Y(MENUSLIDER_BIGGEST_BAR + y))) { \ + m_nHoverOption = decreaseAction; \ + break; \ + } \ + if (!CheckHover(MENU_X(3.0f) + lastActiveBarX, hoverEndX, MENU_Y(y), MENU_Y(MENUSLIDER_BIGGEST_BAR + y))) { \ + m_nHoverOption = HOVEROPTION_NOT_HOVERING; \ + break; \ + } \ + m_nHoverOption = increaseAction; \ + if (m_nMousePosX < MENU_X_LEFT_ALIGNED(MENUSLIDER_X)) \ + m_nHoverOption = HOVEROPTION_NOT_HOVERING; \ + \ + if (onlyWhenHoveringRow && (m_nMousePosY < MENU_Y(y) || m_nMousePosY > MENU_Y(MENUSLIDER_BIGGEST_BAR + y))) \ + m_nHoverOption = HOVEROPTION_NOT_HOVERING; \ + } while(0) + +// --- Functions not in the game/inlined starts + +inline void +CMenuManager::ScrollUpListByOne() +{ + if (m_nSelectedListRow == m_nFirstVisibleRowOnList) { + if (m_nFirstVisibleRowOnList > 0) { + m_nSelectedListRow--; + m_nFirstVisibleRowOnList--; + m_nScrollbarTopMargin -= SCROLLBAR_MAX_HEIGHT / m_nTotalListRow; + } + } else { + m_nSelectedListRow--; + } +} + +inline void +CMenuManager::ScrollDownListByOne() +{ + if (m_nSelectedListRow == m_nFirstVisibleRowOnList + MAX_VISIBLE_OPTION_ON_SCREEN - 1) { + if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN) { + m_nSelectedListRow++; + m_nFirstVisibleRowOnList++; + m_nScrollbarTopMargin += SCROLLBAR_MAX_HEIGHT / m_nTotalListRow; + } + } else { + if (m_nSelectedListRow < m_nTotalListRow - 1) { + m_nSelectedListRow++; + } + } +} + +inline void +CMenuManager::PageUpList(bool playSoundOnSuccess) +{ + if (m_nTotalListRow > MAX_VISIBLE_OPTION_ON_SCREEN) { + if (m_nFirstVisibleRowOnList > 0) { + if(playSoundOnSuccess) + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + + m_nFirstVisibleRowOnList = Max(0, m_nFirstVisibleRowOnList - MAX_VISIBLE_OPTION_ON_SCREEN); + m_nSelectedListRow = Min(m_nSelectedListRow, m_nFirstVisibleRowOnList + MAX_VISIBLE_OPTION_ON_SCREEN - 1); + } else { + m_nFirstVisibleRowOnList = 0; + m_nSelectedListRow = 0; + } + m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; + } +} + +inline void +CMenuManager::PageDownList(bool playSoundOnSuccess) +{ + if (m_nTotalListRow > MAX_VISIBLE_OPTION_ON_SCREEN) { + if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN) { + if(playSoundOnSuccess) + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + + m_nFirstVisibleRowOnList = Min(m_nFirstVisibleRowOnList + MAX_VISIBLE_OPTION_ON_SCREEN, m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN); + m_nSelectedListRow = Max(m_nSelectedListRow, m_nFirstVisibleRowOnList); + } else { + m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN; + m_nSelectedListRow = m_nTotalListRow - 1; + } + m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; + } +} + +#ifdef CUSTOM_FRONTEND_OPTIONS +#define PLUS_LINE_HEIGHT_ON_SCREEN + (aScreens[m_nCurrScreen].layout ? aScreens[m_nCurrScreen].layout->lineHeight : MENU_DEFAULT_LINE_HEIGHT) +bool ScreenHasOption(int screen, const char* gxtKey) +{ + for (int i = 0; i < NUM_MENUROWS; i++) { + if (strcmp(gxtKey, aScreens[screen].m_aEntries[i].m_EntryName) == 0) + return true; + } + return false; +} + +inline void +CMenuManager::ThingsToDoBeforeLeavingPage() +{ + if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && strcmp(m_aSkinName, m_PrefsSkinFile) != 0) { + CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); + + } else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) + m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex(); + + DMAudio.StopFrontEndTrack(); + OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); + + } else if (ScreenHasOption(m_nCurrScreen, "FED_RES")) { + m_nDisplayVideoMode = m_nPrefsVideoMode; + } + + if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { + CPlayerSkin::EndFrontendSkinEdit(); + } + +#ifdef SCROLLABLE_PAGES + if (SCREEN_HAS_AUTO_SCROLLBAR) { + m_nSelectedListRow = 0; + m_nFirstVisibleRowOnList = 0; + m_nScrollbarTopMargin = 0; + } +#endif + + CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption]; + + if (option.m_Action == MENUACTION_CFO_DYNAMIC) + if(option.m_CFODynamic->buttonPressFunc) + option.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); + + if (option.m_Action == MENUACTION_CFO_SELECT && option.m_CFOSelect->onlyApplyOnEnter && option.m_CFOSelect->lastSavedValue != option.m_CFOSelect->displayedValue) + option.m_CFOSelect->displayedValue = *option.m_CFO->value = option.m_CFOSelect->lastSavedValue; + + if (aScreens[m_nCurrScreen].returnPrevPageFunc) { + aScreens[m_nCurrScreen].returnPrevPageFunc(); + } +} + +inline int8 +CMenuManager::GetPreviousPageOption() +{ + int8 prevPage = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage : + (m_nCurrScreen == MENUPAGE_NEW_GAME || m_nCurrScreen == MENUPAGE_OPTIONS || m_nCurrScreen == MENUPAGE_EXIT ? MENUPAGE_START_MENU : aScreens[m_nCurrScreen].m_PreviousPage); + + if (prevPage == -1) // Game also does same + return 0; + + prevPage = prevPage == MENUPAGE_NONE ? (!m_bGameNotLoaded ? MENUPAGE_PAUSE_MENU : MENUPAGE_START_MENU) : prevPage; + + for (int i = 0; i < NUM_MENUROWS; i++) { + if (aScreens[prevPage].m_aEntries[i].m_Action >= MENUACTION_NOTHING) { // CFO check + if (aScreens[prevPage].m_aEntries[i].m_TargetMenu == m_nCurrScreen) { + return i; + } + } + } + + // This shouldn't happen + return 0; +} + +#else +#define PLUS_LINE_HEIGHT_ON_SCREEN + MENU_DEFAULT_LINE_HEIGHT +inline void +CMenuManager::ThingsToDoBeforeLeavingPage() +{ + switch (m_nCurrScreen) { + case MENUPAGE_SOUND_SETTINGS: + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) + m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex(); + + DMAudio.StopFrontEndTrack(); + OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); + break; + case MENUPAGE_DISPLAY_SETTINGS: + m_nDisplayVideoMode = m_nPrefsVideoMode; + break; + case MENUPAGE_SKIN_SELECT: + if (strcmp(m_aSkinName, m_PrefsSkinFile) != 0) + CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); + + CPlayerSkin::EndFrontendSkinEdit(); + break; + } + +#ifdef SCROLLABLE_PAGES + if (SCREEN_HAS_AUTO_SCROLLBAR) { + m_nSelectedListRow = 0; + m_nFirstVisibleRowOnList = 0; + m_nScrollbarTopMargin = 0; + } +#endif +} + +inline int8 +CMenuManager::GetPreviousPageOption() +{ + return (!m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry : + (m_nCurrScreen == MENUPAGE_NEW_GAME ? 0 : (m_nCurrScreen == MENUPAGE_OPTIONS ? 1 : (m_nCurrScreen == MENUPAGE_EXIT ? 2 : aScreens[m_nCurrScreen].m_ParentEntry)))); +} +#endif + +// ------ Functions not in the game/inlined ends + +bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha); +void DoRWStuffEndOfFrame(void); + +void +CMenuManager::SwitchToNewScreen(int8 screen) +{ + bMenuChangeOngoing = true; + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DrawBackground(true); + DoRWStuffEndOfFrame(); + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DrawBackground(true); + DoRWStuffEndOfFrame(); + m_nPrevScreen = m_nCurrScreen; + m_ShowEmptyBindingError = false; + ResetHelperText(); + + ThingsToDoBeforeLeavingPage(); + + if (screen == -2) { + int oldScreen = aScreens[m_nCurrScreen].m_PreviousPage; + int oldOption = GetPreviousPageOption(); + + m_nCurrOption = oldOption; + m_nCurrScreen = oldScreen; + } else if (screen == 0) { + m_nCurrScreen = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu; + m_nCurrOption = 0; + } else { + m_nCurrOption = 0; + m_nCurrScreen = screen; + } + SETUP_SCROLLING(m_nCurrScreen) + + if (hasNativeList(m_nPrevScreen)) + m_nTotalListRow = 0; + + if (m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT) + m_nCurrOption = 8; + m_nMenuFadeAlpha = 0; + m_nOptionHighlightTransitionBlend = 0; + m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); +} + +CMenuManager::CMenuManager() +{ + m_StatsScrollSpeed = 150.0f; + m_StatsScrollDirection = 1; + m_PrefsSfxVolume = 49; + m_PrefsMusicVolume = 49; + m_PrefsRadioStation = 0; + m_PrefsStereoMono = 1; + m_PrefsBrightness = 256; + m_PrefsLOD = CRenderer::ms_lodDistScale; + m_KeyPressedCode = -1; + m_bFrontEnd_ReloadObrTxtGxt = false; + m_PrefsMP3BoostVolume = 0; + m_PrefsShowSubtitles = 0; + m_PrefsShowLegends = 1; +#ifdef ASPECT_RATIO_SCALE + m_PrefsUseWideScreen = AR_AUTO; +#else + m_PrefsUseWideScreen = 0; +#endif + m_PrefsVsync = 0; + m_PrefsVsyncDisp = 1; + m_PrefsFrameLimiter = 1; + m_PrefsLanguage = 0; + field_54 = 0; + m_PrefsAllowNastyGame = 1; + m_PrefsSpeakers = 0; + field_8 = 0; + m_PrefsUseVibration = 0; + m_PrefsShowHud = 1; + m_PrefsRadarMode = 0; + m_DisplayControllerOnFoot = false; + m_bShutDownFrontEndRequested = false; + m_bStartUpFrontEndRequested = false; + pEditString = nil; + pControlEdit = nil; + DisplayComboButtonErrMsg = false; + m_PrefsDMA = 1; + OS_Language = LANG_ENGLISH; + m_ControlMethod = CONTROL_STANDARD; +#ifdef PC_PLAYER_CONTROLS + CCamera::m_bUseMouse3rdPerson = true; +#else + CCamera::m_bUseMouse3rdPerson = false; +#endif + m_lastWorking3DAudioProvider = 0; + m_nFirstVisibleRowOnList = 0; + m_nScrollbarTopMargin = 0.0f; + m_nSelectedListRow = 0; + m_nSkinsTotal = 0; + m_nPrefsAudio3DProviderIndex = AUDIO_PROVIDER_NOT_DETERMINED; + m_bGameNotLoaded = true; + m_nMousePosX = m_nMouseTempPosX; + m_nMousePosY = m_nMouseTempPosY; + m_nMouseOldPosX = m_nMousePosX; + m_nMouseOldPosY = m_nMousePosY; + m_bShowMouse = true; + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + + DMAudio.SetMP3BoostVolume(m_PrefsMP3BoostVolume); + m_bMenuActive = false; + m_bActivateSaveMenu = false; + m_bWantToLoad = false; + m_nMenuFadeAlpha = 0; + m_OnlySaveMenu = false; + m_fMapSize = MENU_Y(162.0f); // Y because of HOR+ + m_fMapCenterX = MENU_X_LEFT_ALIGNED(320.0f); + m_fMapCenterY = MENU_Y(225.0f); + DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); + DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); + +#ifdef NO_ISLAND_LOADING + m_PrefsIslandLoading = ISLAND_LOADING_LOW; +#endif + +#ifdef GAMEPAD_MENU + m_PrefsControllerType = CONTROLLER_XBOXONE; +#endif +} + +void +CMenuManager::SetFrontEndRenderStates(void) +{ + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); +} + +void +CMenuManager::Initialise(void) +{ + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + m_AllowNavigation = false; + m_firstStartCounter = -50; // to start from black + m_nMenuFadeAlpha = 0; + m_nCurrOption = 0; + m_nOptionHighlightTransitionBlend = 0; + CentreMousePointer(); + m_bShowMouse = true; + m_fMapSize = MENU_Y(162.0f); // Y because of HOR+ + m_fMapCenterX = MENU_X_LEFT_ALIGNED(320.0f); + m_fMapCenterY = MENU_Y(225.0f); + CPad::StopPadsShaking(); + if (!m_OnlySaveMenu) + m_nCurrScreen = MENUPAGE_NONE; + DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_STARTING, 0); + DMAudio.Service(); + DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); + DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); +#ifdef FIX_BUGS + static bool firstTime = true; + if (firstTime) { + DMAudio.SetRadioInCar(m_PrefsRadioStation); + firstTime = false; + } else +#endif + m_PrefsRadioStation = DMAudio.GetRadioInCar(); + + DMAudio.SetMP3BoostVolume(m_PrefsMP3BoostVolume); + if (DMAudio.IsMP3RadioChannelAvailable()) { + if (m_PrefsRadioStation < WILDSTYLE || m_PrefsRadioStation > USERTRACK) + m_PrefsRadioStation = CGeneral::GetRandomNumber() % (USERTRACK + 1); + } else if (m_PrefsRadioStation < WILDSTYLE || m_PrefsRadioStation > WAVE) + m_PrefsRadioStation = CGeneral::GetRandomNumber() % (WAVE + 1); + + CFileMgr::SetDir(""); + //CFileMgr::SetDir(""); + PcSaveHelper.PopulateSlotInfo(); + CTimer::StartUserPause(); +} + +void +CMenuManager::CentreMousePointer() +{ + if (SCREEN_WIDTH * 0.5f != 0.0f && 0.0f != SCREEN_HEIGHT * 0.5f) { +#if defined RW_D3D9 || defined RWLIBS + tagPOINT Point; + Point.x = SCREEN_WIDTH / 2; + Point.y = SCREEN_HEIGHT / 2; + ClientToScreen(PSGLOBAL(window), &Point); + SetCursorPos(Point.x, Point.y); +#elif defined RW_GL3 + glfwSetCursorPos(PSGLOBAL(window), SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2); +#endif + + PSGLOBAL(lastMousePos.x) = SCREEN_WIDTH / 2; + PSGLOBAL(lastMousePos.y) = SCREEN_HEIGHT / 2; + } +} + +void +CMenuManager::CheckCodesForControls(int typeOfControl) +{ + DisplayComboButtonErrMsg = false; + bool invalidKey = false; + bool escPressed = false; + eControllerType typeToSave; + // GetStartOptionsCntrlConfigScreens(); + e_ControllerAction action = (e_ControllerAction) m_CurrCntrlAction; + + if (typeOfControl == KEYBOARD) { + if (*pControlEdit == rsESC) { + escPressed = true; + } else if (*pControlEdit != rsF1 && *pControlEdit != rsF2 && *pControlEdit != rsF3 && *pControlEdit != rsF9 && + *pControlEdit != rsLWIN && *pControlEdit != rsRWIN && *pControlEdit != rsRALT) { + typeToSave = KEYBOARD; + if (ControlsManager.GetControllerKeyAssociatedWithAction(action, KEYBOARD) != rsNULL && + *pControlEdit != ControlsManager.GetControllerKeyAssociatedWithAction(action, KEYBOARD)) { + typeToSave = OPTIONAL_EXTRA; + } + } else { + invalidKey = true; + } + } else if (typeOfControl == MOUSE) { + typeToSave = MOUSE; + } else if (typeOfControl == JOYSTICK) { + typeToSave = JOYSTICK; + if (ControlsManager.GetIsActionAButtonCombo(action)) + DisplayComboButtonErrMsg = true; + } + +#ifdef FIX_BUGS + if(!escPressed && !invalidKey) +#endif + ControlsManager.ClearSettingsAssociatedWithAction(action, typeToSave); + + if (!DisplayComboButtonErrMsg && !escPressed && !invalidKey) { + if (typeOfControl == KEYBOARD) { + ControlsManager.DeleteMatchingActionInitiators(action, *pControlEdit, KEYBOARD); + ControlsManager.DeleteMatchingActionInitiators(action, *pControlEdit, OPTIONAL_EXTRA); + } else if (typeOfControl == MOUSE) { + ControlsManager.DeleteMatchingActionInitiators(action, MouseButtonJustClicked, MOUSE); + } else if (typeOfControl == JOYSTICK) { + ControlsManager.DeleteMatchingActionInitiators(action, JoyButtonJustClicked, JOYSTICK); + } + + if (typeOfControl == KEYBOARD) { + ControlsManager.SetControllerKeyAssociatedWithAction(action, *pControlEdit, typeToSave); + } else if (typeOfControl == MOUSE) { + ControlsManager.SetControllerKeyAssociatedWithAction(action, MouseButtonJustClicked, typeToSave); + } else if (typeOfControl == JOYSTICK) { + ControlsManager.SetControllerKeyAssociatedWithAction(action, JoyButtonJustClicked, typeToSave); + } + pControlEdit = nil; + m_bWaitingForNewKeyBind = false; + m_KeyPressedCode = -1; + m_bStartWaitingForKeyBind = false; +#ifdef LOAD_INI_SETTINGS + SaveINIControllerSettings(); +#else + SaveSettings(); +#endif + } +} + +bool +CMenuManager::CheckHover(int x1, int x2, int y1, int y2) +{ + return m_nMousePosX > x1 && m_nMousePosX < x2 && + m_nMousePosY > y1 && m_nMousePosY < y2; +} + +void +CMenuManager::CheckSliderMovement(int value) +{ + switch (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action) { + case MENUACTION_BRIGHTNESS: + m_PrefsBrightness += value * 24.19f; + m_PrefsBrightness = clamp(m_PrefsBrightness, 0, 384); + break; + case MENUACTION_DRAWDIST: + if(value > 0) + m_PrefsLOD += ((1.8f - 0.925f) / 16.0f); + else + m_PrefsLOD -= ((1.8f - 0.925f) / 16.0f); + m_PrefsLOD = clamp(m_PrefsLOD, 0.925f, 1.8f); + CRenderer::ms_lodDistScale = m_PrefsLOD; + break; + case MENUACTION_MUSICVOLUME: + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { + m_PrefsMusicVolume += value * (128 / 32); + m_PrefsMusicVolume = clamp(m_PrefsMusicVolume, 0, 65); + DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); + } + break; + case MENUACTION_SFXVOLUME: + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { + m_PrefsSfxVolume += value * (128 / 32); + m_PrefsSfxVolume = clamp(m_PrefsSfxVolume, 0, 65); + DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); + } + break; + case MENUACTION_MP3VOLUMEBOOST: + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { + if (DMAudio.IsMP3RadioChannelAvailable()) { + m_PrefsMP3BoostVolume += value * (128 / 32); + m_PrefsMP3BoostVolume = clamp(m_PrefsMP3BoostVolume, 0, 65); + DMAudio.SetMP3BoostVolume(m_PrefsMP3BoostVolume); + } + } + break; + case MENUACTION_MOUSESENS: + TheCamera.m_fMouseAccelHorzntl += value * 1.0f/200.0f/15.0f; // ??? + TheCamera.m_fMouseAccelHorzntl = clamp(TheCamera.m_fMouseAccelHorzntl, 1.0f/3200.0f, 1.0f/200.0f); +#ifdef FIX_BUGS + TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl + 0.0005f; +#endif + break; + default: + return; + } + SaveSettings(); +} + +void +CMenuManager::DisplayHelperText(char *text) +{ + if (m_nMenuFadeAlpha != 255) + return; + + // there was a unused static bool + static PauseModeTime LastFlash = 0; + int32 alpha = 255; + + CFont::SetRightJustifyOn(); + CFont::SetScale(SCREEN_SCALE_X(SMALLESTTEXT_X_SCALE), SCREEN_SCALE_Y(SMALLESTTEXT_Y_SCALE)); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetDropShadowPosition(0); + + // We're using SCREEN_STRETCH_FROM_RIGHT, because we also stretch black borders + if (text) { + CFont::SetColor(CRGBA(255, 255, 255, 255)); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get(text)); + return; + } + + if (m_nHelperTextMsgId != 0 && m_nHelperTextMsgId != 1) { + if (CTimer::GetTimeInMillisecondsPauseMode() - LastFlash > 10) { + LastFlash = CTimer::GetTimeInMillisecondsPauseMode(); + m_nHelperTextAlpha -= 2; + } + + if (m_nHelperTextAlpha < 1) + ResetHelperText(); + + alpha = m_nHelperTextAlpha > 255 ? 255 : m_nHelperTextAlpha; + } + + CFont::SetColor(CRGBA(255, 255, 255, alpha)); + // TODO: name this cases? + switch (m_nHelperTextMsgId) { + case 1: + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_APP")); + break; + case 2: + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_HRD")); + break; + case 3: + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_RSO")); + break; + case 4: + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_STS")); + break; + case 5: + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_RSC")); + break; + default: + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_NO) + return; + + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_MUSICVOLUME || + aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_SFXVOLUME) { + + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), + m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER ? TheText.Get("FEH_NA") : TheText.Get("FET_MIG")); + return; + } + + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_KEYBOARDCTRLS) + return; + + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_SCREENRES) { + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), + m_bGameNotLoaded ? TheText.Get("FET_MIG") : TheText.Get("FEH_NA")); + return; + } + + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_AUDIOHW || + aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_SPEAKERCONF) { + + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), + m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER ? TheText.Get("FEH_NA") : TheText.Get("FET_MIG")); + return; + } + + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_RESTOREDEF) + return; + + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_MP3VOLUMEBOOST) { + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), + m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER ? TheText.Get("FEH_NA") : TheText.Get("FET_MIG")); + return; + } + + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), + m_nCurrScreen != MENUPAGE_STATS ? TheText.Get("FET_MIG") : TheText.Get("FEH_SSA")); + + break; + } +} + +int +CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostRightBarSize, float rectSize, float progress, float spacing) +{ + CRGBA color; + float maxBarHeight; + + int lastActiveBarX = 0; + float curBarX = 0.0f; + for (int i = 0; i < 16; i++) { + curBarX = i * rectSize/16.0f + x; + + if (i / 16.0f + 1 / 32.0f < progress) { + color = CRGBA(SLIDERON_COLOR.r, SLIDERON_COLOR.g, SLIDERON_COLOR.b, FadeIn(255)); + lastActiveBarX = curBarX; + } else + color = CRGBA(SLIDEROFF_COLOR.r, SLIDEROFF_COLOR.g, SLIDEROFF_COLOR.b, FadeIn(255)); + + maxBarHeight = Max(mostLeftBarSize, mostRightBarSize); + + float curBarFreeSpace = ((16 - i) * mostLeftBarSize + i * mostRightBarSize) / 16.0f; + float left = curBarX; + float top = y + maxBarHeight - curBarFreeSpace; + float right = spacing + curBarX; + float bottom = y + maxBarHeight; + float shadowOffset = SCREEN_SCALE_X(2.0f); + CSprite2d::DrawRect(CRect(left + shadowOffset, top + shadowOffset, right + shadowOffset, bottom + shadowOffset), CRGBA(0, 0, 0, FadeIn(200))); // Shadow + CSprite2d::DrawRect(CRect(left, top, right, bottom), color); + } + return lastActiveBarX; +} + +void +CMenuManager::DoSettingsBeforeStartingAGame() +{ +#ifdef LEGACY_MENU_OPTIONS + if (m_PrefsVsyncDisp != m_PrefsVsync) + m_PrefsVsync = m_PrefsVsyncDisp; +#endif + DMAudio.DestroyAllGameCreatedEntities(); + DMAudio.Service(); + m_bShutDownFrontEndRequested = true; + m_bWantToRestart = true; + DMAudio.SetEffectsFadeVol(0); + DMAudio.SetMusicFadeVol(0); + for (int i = 0; i < NUM_RADIOS; i++) + CStats::FavoriteRadioStationList[i] = 0.0f; + + SwitchMenuOnAndOff(); + DMAudio.ResetTimers(CTimer::GetTimeInMilliseconds()); +} + +void +CMenuManager::DrawStandardMenus(bool activeScreen) +{ + float nextYToUse = 0.0f; // III leftover, set but unused in VC + bool itemsAreSelectable = true; + CFont::SetBackgroundOff(); + CFont::SetPropOn(); + CFont::SetCentreOff(); + CFont::SetJustifyOn(); + CFont::SetBackGroundOnlyTextOff(); + +#ifdef CUSTOM_FRONTEND_OPTIONS + const int xMargin = aScreens[m_nCurrScreen].layout && aScreens[m_nCurrScreen].layout->xMargin != 0 ? aScreens[m_nCurrScreen].layout->xMargin : MENU_X_MARGIN; +#else + const int xMargin = MENU_X_MARGIN; +#endif + + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(xMargin)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(xMargin)); +#ifdef ASPECT_RATIO_SCALE + CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); +#else + CFont::SetCentreSize(SCREEN_WIDTH); +#endif + + switch (m_nCurrScreen) { + case MENUPAGE_CHOOSE_LOAD_SLOT: + case MENUPAGE_CHOOSE_DELETE_SLOT: + case MENUPAGE_CHOOSE_SAVE_SLOT: + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(38.0f), MENU_Y(85.0f), + MENU_X_LEFT_ALIGNED(615.0f), MENU_Y(75.0f), + MENU_X_LEFT_ALIGNED(30.0f), MENU_Y(320.0f), + MENU_X_LEFT_ALIGNED(605.0f), MENU_Y(330.0f), CRGBA(LIST_BACKGROUND_COLOR.r, LIST_BACKGROUND_COLOR.g, LIST_BACKGROUND_COLOR.b, FadeIn(LIST_BACKGROUND_COLOR.a))); + break; + case MENUPAGE_SOUND_SETTINGS: + PrintRadioSelector(); + break; + case MENUPAGE_STATS: + PrintStats(); + break; + case MENUPAGE_BRIEFS: + PrintBriefs(); + break; + } + + // Page name + if (aScreens[m_nCurrScreen].m_ScreenName[0] != '\0') { + + SET_FONT_FOR_MENU_HEADER + CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X) - MENU_X(7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + + CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255))); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + } + + // Label + wchar *str; + if (aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL) { + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENULABEL_X_MARGIN)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENULABEL_X_MARGIN)); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetScale(MENU_X(BIGTEXT2_X_SCALE), MENU_Y(BIGTEXT2_Y_SCALE)); + CFont::SetRightJustifyOff(); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); + + switch (m_nCurrScreen) { + case MENUPAGE_LOAD_SLOT_CONFIRM: + if (m_bGameNotLoaded) + str = TheText.Get("FES_LCG"); + else + str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); + break; + case MENUPAGE_DELETE_SLOT_CONFIRM: + str = TheText.Get(aScreens[MENUPAGE_DELETE_SLOT_CONFIRM].m_aEntries[0].m_EntryName); + break; + case MENUPAGE_SAVE_OVERWRITE_CONFIRM: + if (Slots[m_nCurrSaveSlot] == SLOT_OK) + str = TheText.Get("FESZ_QO"); + else if (Slots[m_nCurrSaveSlot] == SLOT_CORRUPTED) + str = TheText.Get("FESZ_QZ"); + else + str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); + break; + case MENUPAGE_EXIT: + if (m_bGameNotLoaded) + str = TheText.Get("FEQ_SRW"); + else + str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); + break; + default: + str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); + break; + } + + CFont::PrintString(MENU_X_LEFT_ALIGNED(100.0f), MENU_Y(97.0f), str); + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(xMargin)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(xMargin)); + } + + if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { + if (m_bWaitingForNewKeyBind) + itemsAreSelectable = false; + + DrawControllerScreenExtraText(-8.0f, MENU_X_LEFT_ALIGNED(350), MENU_DEFAULT_LINE_HEIGHT); + } + + wchar unicodeTemp[64]; +#ifdef ASPECT_RATIO_SCALE + char asciiTemp[32]; +#endif + + bool weHaveLabel = aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL; + uint8 section = 0; // 0: highlight trapezoid 1: texts + + while (section < 2) { +#endif + +#ifdef SCROLLABLE_PAGES + int firstOption = SCREEN_HAS_AUTO_SCROLLBAR ? m_nFirstVisibleRowOnList : 0; + int scrollOffset = aScreens[m_nCurrScreen].m_aEntries[firstOption].m_Y - aScreens[m_nCurrScreen].m_aEntries[0].m_Y; + for (int i = firstOption; i < firstOption + MAX_VISIBLE_OPTION && i < NUM_MENUROWS; ++i) { +#else + for (int i = 0; i < NUM_MENUROWS; ++i) { +#endif + wchar* rightText = nil; + wchar* leftText; + if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot >= SAVESLOT_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot <= SAVESLOT_8) { + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetScale(MENU_X(MEDIUMTEXT_X_SCALE), MENU_Y(MEDIUMTEXT_Y_SCALE)); + CFont::SetDropShadowPosition(0); + } else { + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); + } + if (aScreens[m_nCurrScreen].m_aEntries[i].m_Align == MENUALIGN_LEFT) { + CFont::SetCentreOff(); + CFont::SetRightJustifyOff(); + } else if (aScreens[m_nCurrScreen].m_aEntries[i].m_Align == MENUALIGN_RIGHT) { + CFont::SetCentreOff(); + CFont::SetRightJustifyOn(); + } else { + CFont::SetRightJustifyOff(); + CFont::SetCentreOn(); + } + if (aScreens[m_nCurrScreen].m_aEntries[i].m_X == 0 && aScreens[m_nCurrScreen].m_aEntries[i].m_Y == 0) { + if (i == 0 || (i == 1 && weHaveLabel)) { +#ifdef CUSTOM_FRONTEND_OPTIONS + aScreens[m_nCurrScreen].m_aEntries[i].m_X = (aScreens[m_nCurrScreen].layout ? aScreens[m_nCurrScreen].layout->startX : MENU_DEFAULT_CONTENT_X); + aScreens[m_nCurrScreen].m_aEntries[i].m_Y = (aScreens[m_nCurrScreen].layout ? aScreens[m_nCurrScreen].layout->startY : MENU_DEFAULT_CONTENT_Y); +#else + aScreens[m_nCurrScreen].m_aEntries[i].m_X = MENU_DEFAULT_CONTENT_X; + aScreens[m_nCurrScreen].m_aEntries[i].m_Y = MENU_DEFAULT_CONTENT_Y; +#endif + + } else { + aScreens[m_nCurrScreen].m_aEntries[i].m_X = aScreens[m_nCurrScreen].m_aEntries[i-1].m_X; + aScreens[m_nCurrScreen].m_aEntries[i].m_Y = aScreens[m_nCurrScreen].m_aEntries[i-1].m_Y PLUS_LINE_HEIGHT_ON_SCREEN; + } + } +#ifdef CUSTOM_FRONTEND_OPTIONS + else if (aScreens[m_nCurrScreen].m_aEntries[i].m_Y == 0) { + aScreens[m_nCurrScreen].m_aEntries[i].m_Y = aScreens[m_nCurrScreen].m_aEntries[i-1].m_Y PLUS_LINE_HEIGHT_ON_SCREEN; + } +#endif + + if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action != MENUACTION_LABEL && aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName[0] != '\0') { + + if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot >= SAVESLOT_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot <= SAVESLOT_8) { + CFont::SetRightJustifyOff(); + + leftText = nil; + if (Slots[i] == SLOT_OK) { + leftText = GetNameOfSavedGame(i); + rightText = GetSavedGameDateAndTime(i); + } + + if (!leftText || leftText[0] == '\0') { + sprintf(gString, "FEM_SL%d", i + 1); + leftText = TheText.Get(gString); + } + } else { + leftText = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName); + } + + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER) { + if (strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FEO_AUD") == 0) { + CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); + } + } + + switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { +#ifdef GAMEPAD_MENU + case MENUACTION_CTRLVIBRATION: + if (m_PrefsUseVibration) + rightText = TheText.Get("FEM_ON"); + else + rightText = TheText.Get("FEM_OFF"); + break; + case MENUACTION_CTRLCONFIG: + switch (CPad::GetPad(0)->Mode) { + case 0: + rightText = TheText.Get("FEC_CF1"); + break; + case 1: + rightText = TheText.Get("FEC_CF2"); + break; + case 2: + rightText = TheText.Get("FEC_CF3"); + break; + case 3: + rightText = TheText.Get("FEC_CF4"); + break; + } + break; + // This one is still in enum and ProcessOnOffMenuOptions, but removed from other places + case MENUACTION_CTRLDISPLAY: + if (m_DisplayControllerOnFoot) + rightText = TheText.Get("FEC_ONF"); + else + rightText = TheText.Get("FEC_INC"); + break; +#endif + case MENUACTION_FRAMESYNC: + rightText = TheText.Get(m_PrefsVsyncDisp ? "FEM_ON" : "FEM_OFF"); + break; + case MENUACTION_FRAMELIMIT: + rightText = TheText.Get(m_PrefsFrameLimiter ? "FEM_ON" : "FEM_OFF"); + break; + case MENUACTION_TRAILS: + rightText = TheText.Get(CMBlur::BlurOn ? "FEM_ON" : "FEM_OFF"); + break; + case MENUACTION_SUBTITLES: + rightText = TheText.Get(m_PrefsShowSubtitles ? "FEM_ON" : "FEM_OFF"); + break; + case MENUACTION_WIDESCREEN: +#ifndef ASPECT_RATIO_SCALE + rightText = TheText.Get(m_PrefsUseWideScreen ? "FEM_ON" : "FEM_OFF"); +#else + switch (m_PrefsUseWideScreen) { + case AR_AUTO: + rightText = TheText.Get("FEM_AUT"); + break; + case AR_4_3: + sprintf(asciiTemp, "4:3"); + AsciiToUnicode(asciiTemp, unicodeTemp); + rightText = unicodeTemp; + break; + case AR_5_4: + sprintf(asciiTemp, "5:4"); + AsciiToUnicode(asciiTemp, unicodeTemp); + rightText = unicodeTemp; + break; + case AR_16_10: + sprintf(asciiTemp, "16:10"); + AsciiToUnicode(asciiTemp, unicodeTemp); + rightText = unicodeTemp; + break; + case AR_16_9: + sprintf(asciiTemp, "16:9"); + AsciiToUnicode(asciiTemp, unicodeTemp); + rightText = unicodeTemp; + break; + case AR_21_9: + sprintf(asciiTemp, "21:9"); + AsciiToUnicode(asciiTemp, unicodeTemp); + rightText = unicodeTemp; + break; + } +#endif + break; + + case MENUACTION_MUSICVOLUME: + case MENUACTION_SFXVOLUME: + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER) + rightText = TheText.Get("FEA_NAH"); + + break; + case MENUACTION_RADIO: + switch (m_PrefsRadioStation) { + case WILDSTYLE: + rightText = TheText.Get("FEA_FM0"); + break; + case FLASH_FM: + rightText = TheText.Get("FEA_FM1"); + break; + case KCHAT: + rightText = TheText.Get("FEA_FM2"); + break; + case FEVER: + rightText = TheText.Get("FEA_FM3"); + break; + case V_ROCK: + rightText = TheText.Get("FEA_FM4"); + break; + case VCPR: + rightText = TheText.Get("FEA_FM5"); + break; + case RADIO_ESPANTOSO: + rightText = TheText.Get("FEA_FM6"); + break; + case EMOTION: + rightText = TheText.Get("FEA_FM7"); + break; + case WAVE: + rightText = TheText.Get("FEA_FM8"); + break; + case USERTRACK: + rightText = TheText.Get("FEA_MP3"); + break; + } + break; + case MENUACTION_LEGENDS: + rightText = TheText.Get(m_PrefsShowLegends ? "FEM_ON" : "FEM_OFF"); + break; + case MENUACTION_RADARMODE: + switch (m_PrefsRadarMode) { + case 0: + rightText = TheText.Get("FED_RDM"); + break; + case 1: + rightText = TheText.Get("FED_RDB"); + break; + case 2: + rightText = TheText.Get("FEM_OFF"); + break; + } + break; + case MENUACTION_HUD: + rightText = TheText.Get(m_PrefsShowHud ? "FEM_ON" : "FEM_OFF"); + break; +#ifdef LEGACY_MENU_OPTIONS + case MENUACTION_SETDBGFLAG: + rightText = TheText.Get(CTheScripts::IsDebugOn() ? "FEM_ON" : "FEM_OFF"); + break; + case MENUACTION_SWITCHBIGWHITEDEBUGLIGHT: + rightText = TheText.Get(gbBigWhiteDebugLightSwitchedOn ? "FEM_ON" : "FEM_OFF"); + break; + case MENUACTION_COLLISIONPOLYS: + rightText = TheText.Get(gbShowCollisionPolys ? "FEM_ON" : "FEM_OFF"); + break; +#endif + case MENUACTION_SHOWHEADBOB: + rightText = TheText.Get(TheCamera.m_bHeadBob ? "FEM_ON" : "FEM_OFF"); + break; + case MENUACTION_INVVERT: + rightText = TheText.Get(MousePointerStateHelper.bInvertVertically ? "FEM_OFF" : "FEM_ON"); + break; + case MENUACTION_SCREENRES: + AsciiToUnicode(_psGetVideoModeList()[m_nDisplayVideoMode], unicodeTemp); + rightText = unicodeTemp; + + if (!m_bGameNotLoaded) { + CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); + } + break; + case MENUACTION_AUDIOHW: + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER) + rightText = TheText.Get("FEA_NAH"); + else if (m_nPrefsAudio3DProviderIndex == -1) + rightText = TheText.Get("FEA_ADP"); + else { + char *rawProvider = DMAudio.Get3DProviderName(m_nPrefsAudio3DProviderIndex); + AsciiToUnicode(rawProvider, unicodeTemp); + char *provider = UnicodeToAscii(unicodeTemp); // genius + strupr(provider); + if (!strcmp(provider, "DIRECTSOUND3D HARDWARE SUPPORT")) { + strcpy(provider, "DSOUND3D HARDWARE SUPPORT"); + } else if (!strcmp(provider, "DIRECTSOUND3D SOFTWARE EMULATION")) { + strcpy(provider, "DSOUND3D SOFTWARE EMULATION"); + } + AsciiToUnicode(provider, unicodeTemp); + rightText = unicodeTemp; + } + break; + case MENUACTION_SPEAKERCONF: { + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER) + rightText = TheText.Get("FEA_NAH"); + else { + switch (m_PrefsSpeakers) { + case 0: + rightText = TheText.Get("FEA_2SP"); + break; + case 1: + rightText = TheText.Get("FEA_EAR"); + break; + case 2: + rightText = TheText.Get("FEA_4SP"); + break; + } + } + break; + } + case MENUACTION_CTRLMETHOD: { + switch (m_ControlMethod) { + case CONTROL_STANDARD: + leftText = TheText.Get("FET_STI"); + break; + case CONTROL_CLASSIC: + leftText = TheText.Get("FET_CTI"); + break; + } + break; + } + case MENUACTION_DYNAMICACOUSTIC: + rightText = TheText.Get(m_PrefsDMA ? "FEM_ON" : "FEM_OFF"); + break; + case MENUACTION_MOUSESTEER: + rightText = TheText.Get(CVehicle::m_bDisableMouseSteering ? "FEM_OFF" : "FEM_ON"); + if (m_ControlMethod == CONTROL_CLASSIC) { + CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); + } + break; + case MENUACTION_MP3VOLUMEBOOST: + if (!DMAudio.IsMP3RadioChannelAvailable()) { + rightText = TheText.Get("FEA_NM3"); + } + break; +#ifdef CUSTOM_FRONTEND_OPTIONS + case MENUACTION_CFO_DYNAMIC: + case MENUACTION_CFO_SELECT: + CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[i]; + if (option.m_Action == MENUACTION_CFO_SELECT) { + if (option.m_CFOSelect->disableIfGameLoaded && !m_bGameNotLoaded) + CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); + + // To whom manipulate option.m_CFO->value of static options externally (like RestoreDef functions) + if (*option.m_CFO->value != option.m_CFOSelect->lastSavedValue) + option.m_CFOSelect->displayedValue = option.m_CFOSelect->lastSavedValue = *option.m_CFO->value; + + if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts || option.m_CFOSelect->displayedValue < 0) + option.m_CFOSelect->displayedValue = 0; + + rightText = TheText.Get(option.m_CFOSelect->rightTexts[option.m_CFOSelect->displayedValue]); + + } else if (option.m_Action == MENUACTION_CFO_DYNAMIC) { + if (option.m_CFODynamic->drawFunc) { + bool isOptionDisabled = false; + rightText = option.m_CFODynamic->drawFunc(&isOptionDisabled, m_nCurrOption == i); + if (isOptionDisabled) + CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); + } + } + break; +#endif + } + + // Highlight trapezoid + if (activeScreen && i == m_nCurrOption && itemsAreSelectable && section == 0) { + + int leftXMax, rightXMin; + + // FIX: Let's don't scale those so GetStringWidth can give us unscaled width, which will be handy to other calculations below that's done without scaling in mind, + // and scaling will be done eventually. + // CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); + CFont::SetScale(BIGTEXT_X_SCALE, BIGTEXT_Y_SCALE); + + wchar *curOptionName = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName); + float curOptionWidth = CFont::GetStringWidth(curOptionName, true); + + if (CFont::Details.centre) { + leftXMax = Max(0, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X - curOptionWidth / 2.f); + rightXMin = Min(DEFAULT_SCREEN_WIDTH, curOptionWidth / 2.f + aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X); + + } else if (!CFont::Details.rightJustify) { + leftXMax = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X; + rightXMin = Min(DEFAULT_SCREEN_WIDTH, curOptionWidth + aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X); + + } else { + leftXMax = Max(0, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X - curOptionWidth); + rightXMin = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X; + } + CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); + + int action = aScreens[m_nCurrScreen].m_aEntries[i].m_Action; + int saveSlot = aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot; + if (rightText || action == MENUACTION_DRAWDIST || action == MENUACTION_BRIGHTNESS || action == MENUACTION_MUSICVOLUME || + action == MENUACTION_SFXVOLUME || action == MENUACTION_MP3VOLUMEBOOST || action == MENUACTION_MOUSESENS || + saveSlot >= SAVESLOT_1 && saveSlot <= SAVESLOT_8) { + rightXMin = 600; + leftXMax = 40; + } + + int y = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Y MINUS_SCROLL_OFFSET; + int topYMax = y; + uint32 bottomYMin = y + MENU_DEFAULT_LINE_HEIGHT - 7; // Decreasing is not recommended. Because this actually is dependent to font scale, not line height. + + // Actually bottomRight and bottomLeft should be exchanged here(although this is original code). + // So this shows us either R* didn't use same struct for menu BG and highlight, or they just kept fields as x1,y1 etc. Yikes. + + if (m_nOptionHighlightTransitionBlend == 0) { + if (m_firstStartCounter == 255 && m_nMenuFadeAlpha == 255 && !bMenuChangeOngoing) { + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(menuOptionHighlight.topLeft_x), MENU_Y(menuOptionHighlight.topLeft_y), + MENU_X_LEFT_ALIGNED(menuOptionHighlight.topRight_x), MENU_Y(menuOptionHighlight.topRight_y), + MENU_X_LEFT_ALIGNED(menuOptionHighlight.bottomRight_x), MENU_Y(menuOptionHighlight.bottomRight_y), + MENU_X_LEFT_ALIGNED(menuOptionHighlight.bottomLeft_x), MENU_Y(menuOptionHighlight.bottomLeft_y), SELECTIONBORDER_COLOR); + } + menuOptionHighlight.SaveCurrentCoors(); + menuOptionHighlight.topLeft_x = leftXMax - 5 - CGeneral::GetRandomNumber() % 10; + menuOptionHighlight.topLeft_y = topYMax - CGeneral::GetRandomNumber() % 7; + menuOptionHighlight.topRight_x = rightXMin + 5 + CGeneral::GetRandomNumber() % 10; + menuOptionHighlight.topRight_y = topYMax - CGeneral::GetRandomNumber() % 7; + menuOptionHighlight.bottomLeft_x = rightXMin + 5 + CGeneral::GetRandomNumber() % 10; + menuOptionHighlight.bottomLeft_y = bottomYMin + CGeneral::GetRandomNumber() % 7; + menuOptionHighlight.bottomRight_x = leftXMax - 5 - CGeneral::GetRandomNumber() % 10; + menuOptionHighlight.bottomRight_y = bottomYMin + CGeneral::GetRandomNumber() % 7; + menuOptionHighlight.UpdateMultipliers(); + menuOptionHighlight.Translate(m_nOptionHighlightTransitionBlend); + + } else if (m_nOptionHighlightTransitionBlend < 255) { + menuOptionHighlight.Translate(m_nOptionHighlightTransitionBlend); + if (m_firstStartCounter == 255 && m_nMenuFadeAlpha == 255 && !bMenuChangeOngoing) { + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(menuOptionHighlight.topLeft_x), MENU_Y(menuOptionHighlight.topLeft_y), + MENU_X_LEFT_ALIGNED(menuOptionHighlight.topRight_x), MENU_Y(menuOptionHighlight.topRight_y), + MENU_X_LEFT_ALIGNED(menuOptionHighlight.bottomRight_x), MENU_Y(menuOptionHighlight.bottomRight_y), + MENU_X_LEFT_ALIGNED(menuOptionHighlight.bottomLeft_x), MENU_Y(menuOptionHighlight.bottomLeft_y), SELECTIONBORDER_COLOR); + } + } else { + m_nOptionHighlightTransitionBlend = 255; + menuOptionHighlight.Translate(m_nOptionHighlightTransitionBlend); + if (m_firstStartCounter == 255 && m_nMenuFadeAlpha == 255 && !bMenuChangeOngoing) { + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(menuOptionHighlight.topLeft_x), MENU_Y(menuOptionHighlight.topLeft_y), + MENU_X_LEFT_ALIGNED(menuOptionHighlight.topRight_x), MENU_Y(menuOptionHighlight.topRight_y), + MENU_X_LEFT_ALIGNED(menuOptionHighlight.bottomRight_x), MENU_Y(menuOptionHighlight.bottomRight_y), + MENU_X_LEFT_ALIGNED(menuOptionHighlight.bottomLeft_x), MENU_Y(menuOptionHighlight.bottomLeft_y), SELECTIONBORDER_COLOR); + } + } + + static PauseModeTime lastBlendChange = 0; + if (m_nOptionHighlightTransitionBlend <= 255) { + static uint32 blendChangeCounter = 0; + if (CTimer::GetTimeInMillisecondsPauseMode() - lastBlendChange > 20 +#ifndef FIX_HIGH_FPS_BUGS_ON_FRONTEND // Dirty dirty hack + || blendChangeCounter > 20 +#endif + ) { + m_nOptionHighlightTransitionBlend += 50; + lastBlendChange = CTimer::GetTimeInMillisecondsPauseMode(); + blendChangeCounter = 0; + } + ++blendChangeCounter; + } + } + + if (section == 1) { + if (leftText) { + CFont::PrintString(MENU_X_LEFT_ALIGNED(aScreens[m_nCurrScreen].m_aEntries[i].m_X), MENU_Y(aScreens[m_nCurrScreen].m_aEntries[i].m_Y MINUS_SCROLL_OFFSET), leftText); + } + + if (rightText) { + CFont::SetCentreOff(); + CFont::SetRightJustifyOn(); + if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot >= SAVESLOT_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot <= SAVESLOT_8) { + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetScale(MENU_X(MEDIUMTEXT_X_SCALE), MENU_Y(MEDIUMTEXT_Y_SCALE)); + } else { + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(DEFAULT_SCREEN_WIDTH - RIGHT_ALIGNED_TEXT_RIGHT_MARGIN(xMargin)), MENU_Y(aScreens[m_nCurrScreen].m_aEntries[i].m_Y MINUS_SCROLL_OFFSET), rightText); + } + + if (m_nPrefsAudio3DProviderIndex == DMAudio.GetCurrent3DProviderIndex()) { + if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH") && m_nHelperTextMsgId == 1) + ResetHelperText(); + } + if (m_nDisplayVideoMode == m_nPrefsVideoMode) { + if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES") && m_nHelperTextMsgId == 1) + ResetHelperText(); + } + if (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) { + if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH")) + SetHelperText(1); + } + if (m_nDisplayVideoMode != m_nPrefsVideoMode) { + if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES")) + SetHelperText(1); + } + if (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) { + if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH") != 0 +#ifdef CUSTOM_FRONTEND_OPTIONS + && ScreenHasOption(m_nCurrScreen, "FEA_3DH") +#else + && m_nCurrScreen == MENUPAGE_SOUND_SETTINGS +#endif + && m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { + + m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex(); + SetHelperText(3); + } + } + if (m_nDisplayVideoMode != m_nPrefsVideoMode) { + if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES") != 0 +#ifdef CUSTOM_FRONTEND_OPTIONS + && ScreenHasOption(m_nCurrScreen, "FED_RES")) { +#else + && m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS) { +#endif + m_nDisplayVideoMode = m_nPrefsVideoMode; + SetHelperText(3); + } + } + + // Sliders + int lastActiveBarX; + switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { + case MENUACTION_BRIGHTNESS: + ProcessSlider(m_PrefsBrightness / 384.0f, 70.0f, HOVEROPTION_INCREASE_BRIGHTNESS, HOVEROPTION_DECREASE_BRIGHTNESS, SCREEN_WIDTH, true); + break; + case MENUACTION_DRAWDIST: + ProcessSlider((m_PrefsLOD - 0.925f) / 0.875f, 99.0f, HOVEROPTION_INCREASE_DRAWDIST, HOVEROPTION_DECREASE_DRAWDIST, SCREEN_WIDTH, true); + break; + case MENUACTION_MUSICVOLUME: + if(m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) + ProcessSlider(m_PrefsMusicVolume / 64.0f, 70.0f, HOVEROPTION_INCREASE_MUSICVOLUME, HOVEROPTION_DECREASE_MUSICVOLUME, SCREEN_WIDTH, true); + break; + case MENUACTION_SFXVOLUME: + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) + ProcessSlider(m_PrefsSfxVolume / 64.0f, 99.0f, HOVEROPTION_INCREASE_SFXVOLUME, HOVEROPTION_DECREASE_SFXVOLUME, SCREEN_WIDTH, true); + break; + case MENUACTION_MOUSESENS: + ProcessSlider(TheCamera.m_fMouseAccelHorzntl * 200.0f, 170.0f, HOVEROPTION_INCREASE_MOUSESENS, HOVEROPTION_DECREASE_MOUSESENS, SCREEN_WIDTH, false); + break; + case MENUACTION_MP3VOLUMEBOOST: + if(m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER && DMAudio.IsMP3RadioChannelAvailable()) + ProcessSlider(m_PrefsMP3BoostVolume / 64.f, 128.0f, HOVEROPTION_INCREASE_MP3BOOST, HOVEROPTION_DECREASE_MP3BOOST, SCREEN_WIDTH, true); + break; + } + + // Not just unused, but also collides with the bug fix in Font.cpp. Yikes. +#ifndef FIX_BUGS + nextYToUse += MENU_DEFAULT_LINE_HEIGHT * CFont::GetNumberLines(MENU_X_LEFT_ALIGNED(60.0f), MENU_Y(nextYToUse), leftText); +#endif + + if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_RADIO) { + nextYToUse += MENURADIO_SELECTOR_HEIGHT + 5.f; // unused + } + } + } + } + section++; + } + +#ifdef SCROLLABLE_PAGES + #define SCROLLBAR_BOTTOM_Y 105.0f // only for background, scrollbar's itself is calculated + #define SCROLLBAR_RIGHT_X 26.0f + #define SCROLLBAR_WIDTH 9.5f + #define SCROLLBAR_TOP_Y 84 + + if (activeScreen && SCREEN_HAS_AUTO_SCROLLBAR) { + // Scrollbar background + CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 2), MENU_Y(SCROLLBAR_TOP_Y), + MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 2 - SCROLLBAR_WIDTH), SCREEN_SCALE_FROM_BOTTOM(SCROLLBAR_BOTTOM_Y)), CRGBA(30, 30, 30, FadeIn(150))); + + float scrollbarHeight = SCROLLBAR_MAX_HEIGHT / (m_nTotalListRow / (float) MAX_VISIBLE_OPTION); + float scrollbarBottom, scrollbarTop; + + scrollbarBottom = MENU_Y(SCROLLBAR_TOP_Y - 6 + m_nScrollbarTopMargin + scrollbarHeight); + scrollbarTop = MENU_Y(SCROLLBAR_TOP_Y + 2 + m_nScrollbarTopMargin); + // Scrollbar shadow + CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 4), scrollbarTop, + MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 1 - SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)), + CRGBA(50, 50, 50, FadeIn(255))); + + // Scrollbar + CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 4), scrollbarTop, + MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - SCROLLBAR_WIDTH), scrollbarBottom), + CRGBA(SCROLLBAR_COLOR.r, SCROLLBAR_COLOR.g, SCROLLBAR_COLOR.b, FadeIn(255))); + + } +#endif + + switch (m_nCurrScreen) { +#ifdef GAMEPAD_MENU + case MENUPAGE_CONTROLLER_SETTINGS: + PrintController(); + break; +#endif + case MENUPAGE_STATS: + case MENUPAGE_CONTROLLER_PC: + case MENUPAGE_SOUND_SETTINGS: + case MENUPAGE_DISPLAY_SETTINGS: + case MENUPAGE_MOUSE_CONTROLS: + DisplayHelperText(nil); + break; + case MENUPAGE_OPTIONS: + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_LOADRADIO) + DisplayHelperText("FEA_NAH"); + break; +#ifdef CUSTOM_FRONTEND_OPTIONS + default: + if (aScreens[m_nCurrScreen].layout) { + if (aScreens[m_nCurrScreen].layout->showLeftRightHelper) { + DisplayHelperText(nil); + } + } + break; +#endif + } + + if (m_nCurrScreen == MENUPAGE_DELETING_IN_PROGRESS) { + SmallMessageScreen("FEDL_WR"); + } +#ifndef XBOX_MESSAGE_SCREEN + else if (m_nCurrScreen == MENUPAGE_SAVING_IN_PROGRESS) { + SmallMessageScreen("FESZ_WR"); + } +#endif +} + +int +CMenuManager::GetNumOptionsCntrlConfigScreens(void) +{ + int number = 0; + switch (m_nCurrScreen) { +#ifdef LEGACY_MENU_OPTIONS + case MENUPAGE_CONTROLLER_PC_OLD3: + number = 2; + break; + case MENUPAGE_CONTROLLER_DEBUG: + number = 4; + break; +#endif + case MENUPAGE_KEYBOARD_CONTROLS: + switch (m_ControlMethod) { + case CONTROL_STANDARD: + number = 27; + break; + case CONTROL_CLASSIC: + number = 32; + break; + } + break; + } + return number; +} + +void +CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 column) +{ + int controllerAction = PED_FIREWEAPON; + // GetStartOptionsCntrlConfigScreens(); + int numOptions = GetNumOptionsCntrlConfigScreens(); + int nextY = MENU_Y(yStart); + int bindingMargin = MENU_X(3.0f); + float rowHeight; + switch (m_ControlMethod) { + case CONTROL_STANDARD: + rowHeight = CONTSETUP_STANDARD_ROW_HEIGHT; + break; + case CONTROL_CLASSIC: + rowHeight = CONTSETUP_CLASSIC_ROW_HEIGHT; + break; + default: + break; + } + + for (int optionIdx = 0; optionIdx < numOptions; nextY = MENU_Y(++optionIdx * rowHeight + yStart)) { + int nextX = xStart; + int bindingsForThisOpt = 0; + int contSetOrder = SETORDER_1; + CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); + + if (column == CONTSETUP_PED_COLUMN) { + switch (optionIdx) { + case 0: + controllerAction = PED_FIREWEAPON; + break; + case 1: + controllerAction = PED_CYCLE_WEAPON_RIGHT; + break; + case 2: + controllerAction = PED_CYCLE_WEAPON_LEFT; + break; + case 3: + controllerAction = GO_FORWARD; + break; + case 4: + controllerAction = GO_BACK; + break; + case 5: + controllerAction = GO_LEFT; + break; + case 6: + controllerAction = GO_RIGHT; + break; + case 7: + controllerAction = PED_SNIPER_ZOOM_IN; + break; + case 8: + controllerAction = PED_SNIPER_ZOOM_OUT; + break; + case 9: + controllerAction = VEHICLE_ENTER_EXIT; + break; + case 10: + case 11: + case 12: + case 16: + case 20: + case 21: + case 22: + case 23: + controllerAction = -1; + break; + case 13: + controllerAction = CAMERA_CHANGE_VIEW_ALL_SITUATIONS; + break; + case 14: + controllerAction = PED_JUMPING; + break; + case 15: + controllerAction = PED_SPRINT; + break; + case 17: + controllerAction = PED_LOCK_TARGET; + break; + case 18: + controllerAction = PED_DUCK; + break; + case 19: + controllerAction = PED_ANSWER_PHONE; + break; + case 24: + controllerAction = PED_LOOKBEHIND; + break; + case 25: + if (m_ControlMethod == CONTROL_STANDARD) + controllerAction = -1; + else + controllerAction = PED_1RST_PERSON_LOOK_LEFT; + break; + case 26: + if (m_ControlMethod == CONTROL_STANDARD) + controllerAction = -1; + else + controllerAction = PED_1RST_PERSON_LOOK_RIGHT; + break; + case 27: + controllerAction = PED_1RST_PERSON_LOOK_UP; + break; + case 28: + controllerAction = PED_1RST_PERSON_LOOK_DOWN; + break; + case 29: + controllerAction = PED_CYCLE_TARGET_LEFT; + break; + case 30: + controllerAction = PED_CYCLE_TARGET_RIGHT; + break; + case 31: + controllerAction = PED_CENTER_CAMERA_BEHIND_PLAYER; + break; + default: + break; + } + } else if (column == CONTSETUP_VEHICLE_COLUMN) { + switch (optionIdx) { + case 0: +#ifdef BIND_VEHICLE_FIREWEAPON + controllerAction = VEHICLE_FIREWEAPON; +#else + controllerAction = PED_FIREWEAPON; +#endif + break; + case 1: + case 2: + case 7: + case 8: + case 14: + case 15: + case 17: + case 18: + case 19: + case 27: + case 28: + case 29: + case 30: + case 31: + controllerAction = -1; + break; + case 3: + controllerAction = VEHICLE_ACCELERATE; + break; + case 4: + controllerAction = VEHICLE_BRAKE; + break; + case 5: + controllerAction = GO_LEFT; + break; + case 6: + controllerAction = GO_RIGHT; + break; + case 9: + controllerAction = VEHICLE_ENTER_EXIT; + break; + case 10: + controllerAction = VEHICLE_CHANGE_RADIO_STATION; + break; + case 11: + controllerAction = VEHICLE_HORN; + break; + case 12: + controllerAction = TOGGLE_SUBMISSIONS; + break; + case 13: + controllerAction = CAMERA_CHANGE_VIEW_ALL_SITUATIONS; + break; + case 16: + controllerAction = VEHICLE_HANDBRAKE; + break; + case 20: + controllerAction = VEHICLE_TURRETLEFT; + break; + case 21: + controllerAction = VEHICLE_TURRETRIGHT; + break; + case 22: + controllerAction = VEHICLE_TURRETUP; + break; + case 23: + controllerAction = VEHICLE_TURRETDOWN; + break; + case 24: + controllerAction = -2; + break; + case 25: + controllerAction = VEHICLE_LOOKLEFT; + break; + case 26: + controllerAction = VEHICLE_LOOKRIGHT; + break; + default: + break; + } + } + + // Highlight selected column(and make its text black) + if (m_nSelectedListRow == optionIdx) { + int bgY = m_nSelectedListRow * rowHeight + yStart + 1.0f; + if (m_nCurrExLayer == HOVEROPTION_LIST) { + + if (column == CONTSETUP_PED_COLUMN && m_nSelectedContSetupColumn == CONTSETUP_PED_COLUMN) { +#ifdef FIX_BUGS + CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), + MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255))); +#else + CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(bgY), + MENU_X_LEFT_ALIGNED(400.0f), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), + CRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255))); +#endif + CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); + + } else if (column == CONTSETUP_VEHICLE_COLUMN && m_nSelectedContSetupColumn == CONTSETUP_VEHICLE_COLUMN) { +#ifdef FIX_BUGS + CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), + MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255))); +#else + CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(410.0f), MENU_Y(bgY), MENU_X_LEFT_ALIGNED(600.0f), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), + CRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255))); +#endif + CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); + } + } + } + + // Print bindings, including seperator (-) between them + + CFont::SetScale(MENU_X(0.25f), MENU_Y(LISTITEM_Y_SCALE)); +#ifdef FIX_BUGS + for (; contSetOrder < MAX_SETORDERS && controllerAction >= 0; contSetOrder++) { +#else + for (; contSetOrder < MAX_SETORDERS && controllerAction != -1; contSetOrder++) { +#endif + wchar *settingText = ControlsManager.GetControllerSettingTextWithOrderNumber((e_ControllerAction)controllerAction, (eContSetOrder)contSetOrder); + if (settingText) { + ++bindingsForThisOpt; + if (bindingsForThisOpt > 1) { + wchar *seperator = TheText.Get("FEC_IBT"); + CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); + CFont::PrintString(nextX, nextY, seperator); + nextX += CFont::GetStringWidth(seperator, true) + bindingMargin; + } + CFont::PrintString(nextX, nextY, settingText); +#ifdef MORE_LANGUAGES + if (CFont::IsJapanese()) + nextX += CFont::GetStringWidth_Jap(settingText) + bindingMargin; + else +#endif + nextX += CFont::GetStringWidth(settingText, true) + bindingMargin; + } + } + if (controllerAction == -1) { + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::PrintString(nextX, nextY, TheText.Get("FEC_NUS")); // not used + + } else if (controllerAction == -2) { + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::PrintString(nextX, nextY, TheText.Get("FEC_CMP")); // combo: l+r + + } else if (bindingsForThisOpt == 0) { + m_NoEmptyBinding = false; + if (m_nSelectedListRow != optionIdx) { + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::PrintString(nextX, nextY, TheText.Get("FEC_UNB")); // unbound + + } else if (m_bWaitingForNewKeyBind) { + if (column != m_nSelectedContSetupColumn) { + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::PrintString(nextX, nextY, TheText.Get("FEC_UNB")); // unbound + } + } else { + if (column != m_nSelectedContSetupColumn) { + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); + } + CFont::PrintString(nextX, nextY, TheText.Get("FEC_UNB")); // unbound + } + } + + if (column == CONTSETUP_PED_COLUMN && m_nSelectedContSetupColumn == CONTSETUP_PED_COLUMN || + column == CONTSETUP_VEHICLE_COLUMN && m_nSelectedContSetupColumn == CONTSETUP_VEHICLE_COLUMN) { + + if (optionIdx == m_nSelectedListRow && controllerAction != -1 && controllerAction != -2) { + m_CurrCntrlAction = controllerAction; + if (m_bWaitingForNewKeyBind) { + static bool showWaitingText = false; + if (bindingsForThisOpt > 0) { + wchar *seperator = TheText.Get("FEC_IBT"); + CFont::PrintString(nextX, nextY, seperator); + nextX += CFont::GetStringWidth(seperator, true) + bindingMargin; + } + static PauseModeTime lastWaitingTextFlash = 0; + if (CTimer::GetTimeInMillisecondsPauseMode() - lastWaitingTextFlash > 150) { + showWaitingText = !showWaitingText; + lastWaitingTextFlash = CTimer::GetTimeInMillisecondsPauseMode(); + } + if (showWaitingText) { + CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); + CFont::PrintString(nextX, nextY, TheText.Get("FEC_QUE")); // "???" + } + if (m_bKeyChangeNotProcessed) + DisplayHelperText("FET_CIG"); + else + DisplayHelperText("FET_RIG"); + + SET_FONT_FOR_LIST_ITEM + + m_bKeyIsOK = true; + } else { + DisplayHelperText("FET_CIG"); + SET_FONT_FOR_LIST_ITEM + + m_bKeyIsOK = false; + m_bKeyChangeNotProcessed = false; + } + } else if (optionIdx == m_nSelectedListRow) { + DisplayHelperText("FET_EIG"); + SET_FONT_FOR_LIST_ITEM + } + } + } +} + +void +CMenuManager::DrawControllerScreenExtraText(int yStart, int xStart, int lineHeight) +{ + int extraTextStart = GetStartOptionsCntrlConfigScreens(); + int numOpts = GetNumOptionsCntrlConfigScreens(); + int spacing = MENU_X(10.0f); + for (int i = extraTextStart; i < extraTextStart + numOpts; i++) { + int numTextsPrinted = 0; + int nextX = xStart; + for (int j = 1; j < 5; j++) { + wchar *text = ControlsManager.GetControllerSettingTextWithOrderNumber((e_ControllerAction)i, (eContSetOrder)j); + if (text) + ++numTextsPrinted; + + if (text) { + // Seperator + if (numTextsPrinted > 1) { + CFont::PrintString(nextX, MENU_Y(yStart), TheText.Get("FEC_IBT")); + nextX = CFont::GetStringWidth(TheText.Get("FEC_IBT"), true) + spacing + nextX; + } + CFont::PrintString(nextX, MENU_Y(yStart), text); + } + if (text) + nextX = CFont::GetStringWidth(text, true) + spacing + nextX; + } + if (m_nCurrOption == i - extraTextStart && m_bWaitingForNewKeyBind) { + static bool waitingTextVisible = false; + + // Seperator + if (numTextsPrinted > 0) { + CFont::PrintString(nextX, MENU_Y(yStart), TheText.Get("FEC_IBT")); + nextX = CFont::GetStringWidth(TheText.Get("FEC_IBT"), true) + spacing + nextX; + } + static PauseModeTime lastStateChange = 0; + if (CTimer::GetTimeInMillisecondsPauseMode() - lastStateChange > 150) { + waitingTextVisible = !waitingTextVisible; + lastStateChange = CTimer::GetTimeInMillisecondsPauseMode(); + } + if (waitingTextVisible) { + CFont::SetColor(CRGBA(255, 255, 0, FadeIn(255))); + CFont::PrintString(nextX, MENU_Y(yStart), TheText.Get("FEC_QUE")); + CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); + } + } + yStart += lineHeight; + } + wchar *error = nil; + if (DisplayComboButtonErrMsg) + error = ControlsManager.GetButtonComboText((e_ControllerAction)(m_nCurrOption + extraTextStart)); + + if (error) { + CFont::SetColor(CRGBA(233, 22, 159, 255)); + CFont::PrintString(xStart, MENU_Y(yStart + 10), error); + } +} + +void +CMenuManager::DrawControllerSetupScreen() +{ + float rowHeight; + switch (m_ControlMethod) { + case CONTROL_STANDARD: + rowHeight = CONTSETUP_STANDARD_ROW_HEIGHT; + break; + case CONTROL_CLASSIC: + rowHeight = CONTSETUP_CLASSIC_ROW_HEIGHT; + break; + default: + break; + } + RESET_FONT_FOR_NEW_PAGE + SET_FONT_FOR_MENU_HEADER + + // Shadow + CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); + + if (m_ControlMethod == CONTROL_STANDARD) + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X) - MENU_X(7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get("FET_STI")); + else if (m_ControlMethod == CONTROL_CLASSIC) + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X) - MENU_X(7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get("FET_CTI")); + + // Real header + CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255))); + + if (m_ControlMethod == CONTROL_STANDARD) + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get("FET_STI")); + else if (m_ControlMethod == CONTROL_CLASSIC) + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get("FET_CTI")); + + wchar *actionTexts[33]; + actionTexts[0] = TheText.Get("FEC_FIR"); + actionTexts[1] = TheText.Get("FEC_NWE"); + actionTexts[2] = TheText.Get("FEC_PWE"); + actionTexts[3] = TheText.Get("FEC_FOR"); + actionTexts[4] = TheText.Get("FEC_BAC"); + actionTexts[5] = TheText.Get("FEC_LEF"); + actionTexts[6] = TheText.Get("FEC_RIG"); + actionTexts[7] = TheText.Get("FEC_ZIN"); + actionTexts[8] = TheText.Get("FEC_ZOT"); + actionTexts[9] = TheText.Get("FEC_EEX"); + actionTexts[10] = TheText.Get("FEC_RAD"); + actionTexts[11] = TheText.Get("FEC_HRN"); + actionTexts[12] = TheText.Get("FEC_SUB"); + actionTexts[13] = TheText.Get("FEC_CMR"); + actionTexts[14] = TheText.Get("FEC_JMP"); + actionTexts[15] = TheText.Get("FEC_SPN"); + actionTexts[16] = TheText.Get("FEC_HND"); + actionTexts[17] = TheText.Get("FEC_TAR"); + actionTexts[18] = TheText.Get("FEC_CRO"); + actionTexts[19] = TheText.Get("FEC_ANS"); + if (m_ControlMethod == CONTROL_CLASSIC) { + actionTexts[20] = TheText.Get("FEC_TFL"); + actionTexts[21] = TheText.Get("FEC_TFR"); + actionTexts[22] = TheText.Get("FEC_TFU"); + actionTexts[23] = TheText.Get("FEC_TFD"); + actionTexts[24] = TheText.Get("FEC_LBA"); + actionTexts[25] = TheText.Get("FEC_LOL"); + actionTexts[26] = TheText.Get("FEC_LOR"); + actionTexts[27] = TheText.Get("FEC_LUD"); + actionTexts[28] = TheText.Get("FEC_LDU"); + actionTexts[29] = TheText.Get("FEC_NTR"); + actionTexts[30] = TheText.Get("FEC_PTT"); + actionTexts[31] = TheText.Get("FEC_CEN"); + actionTexts[32] = nil; + } else { + actionTexts[20] = TheText.Get("FEC_TFL"); + actionTexts[21] = TheText.Get("FEC_TFR"); + actionTexts[22] = TheText.Get("FEC_TFU"); + actionTexts[23] = TheText.Get("FEC_TFD"); + actionTexts[24] = TheText.Get("FEC_LBA"); + actionTexts[25] = TheText.Get("FEC_LOL"); + actionTexts[26] = TheText.Get("FEC_LOR"); + actionTexts[27] = nil; + } + + // Blue panel background + CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(CONTSETUP_LIST_LEFT), MENU_Y(CONTSETUP_LIST_TOP), + MENU_X_RIGHT_ALIGNED(CONTSETUP_LIST_RIGHT), SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_LIST_BOTTOM)), + CRGBA(LIST_BACKGROUND_COLOR.r, LIST_BACKGROUND_COLOR.g, LIST_BACKGROUND_COLOR.b, FadeIn(LIST_BACKGROUND_COLOR.a))); + + if (m_nCurrExLayer == HOVEROPTION_LIST) + CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255))); + else + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); + + // List header + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT)); + CFont::SetRightJustifyOff(); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::PrintString(MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X), MENU_Y(CONTSETUP_LIST_TOP), TheText.Get("FET_CFT")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X), MENU_Y(CONTSETUP_LIST_TOP), TheText.Get("FET_CCR")); + CFont::SetDropShadowPosition(0); + SET_FONT_FOR_LIST_ITEM + + int yStart; + if (m_ControlMethod == CONTROL_CLASSIC) + yStart = CONTSETUP_LIST_TOP + 18; + else + yStart = CONTSETUP_LIST_TOP + 21; + + float optionYBottom = yStart + rowHeight; + for (int i = 0; i < ARRAY_SIZE(actionTexts); ++i) { + wchar *actionText = actionTexts[i]; + if (!actionText) + break; + + if (!m_bWaitingForNewKeyBind) { + if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_LIST_LEFT - 10.0f) && + m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X + CONTSETUP_BOUND_COLUMN_WIDTH)) { + + if (m_nMousePosY > MENU_Y(i * rowHeight + yStart) && m_nMousePosY < MENU_Y(i * rowHeight + optionYBottom)) { + m_nOptionMouseHovering = i; + if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { + m_nCurrExLayer = HOVEROPTION_LIST; + m_nSelectedListRow = i; + + // why different number for 3rd column hovering X?? this function is a mess +#ifdef FIX_BUGS + if (m_nMousePosX > MENU_X_LEFT_ALIGNED(0.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH)) { +#else + if (m_nMousePosX > MENU_X_LEFT_ALIGNED(0.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(370.0f)) { +#endif + m_nSelectedContSetupColumn = CONTSETUP_PED_COLUMN; +#ifdef FIX_BUGS + } else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH) && m_nMousePosX < SCREEN_WIDTH) { +#else + } else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(370.0f) && m_nMousePosX < SCREEN_WIDTH) { +#endif + m_nSelectedContSetupColumn = CONTSETUP_VEHICLE_COLUMN; + } + } + // what?? + if (m_nHoverOption == HOVEROPTION_SKIN) { + if (i == m_nSelectedListRow) { + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + m_bWaitingForNewKeyBind = true; + m_bStartWaitingForKeyBind = true; + pControlEdit = &m_KeyPressedCode; + } + } else + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + } + } + } + if (m_nSelectedListRow != i) + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); + else if (m_nCurrExLayer == HOVEROPTION_LIST) + CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255))); + + CFont::SetRightJustifyOff(); + if (m_PrefsLanguage == LANGUAGE_GERMAN && (i == 20 || i == 21 || i == 22 || i == 23)) + CFont::SetScale(MENU_X(0.32f), MENU_Y(LISTITEM_Y_SCALE)); + else + CFont::SetScale(MENU_X(LISTITEM_X_SCALE), MENU_Y(LISTITEM_Y_SCALE)); + + CFont::PrintString(MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_1_X), MENU_Y(i * rowHeight + yStart), actionText); + } + DrawControllerBound(yStart, MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X), rowHeight, CONTSETUP_PED_COLUMN); + DrawControllerBound(yStart, MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X), rowHeight, CONTSETUP_VEHICLE_COLUMN); + + if (!m_bWaitingForNewKeyBind) { + CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); + + if ((m_nMousePosX > MENU_X_RIGHT_ALIGNED(CONTSETUP_BACK_RIGHT) - CFont::GetStringWidth(TheText.Get("FEDS_TB"), true) + && m_nMousePosX < MENU_X_RIGHT_ALIGNED(CONTSETUP_BACK_RIGHT) && m_nMousePosY > SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_BACK_BOTTOM) + && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_BACK_BOTTOM - CONTSETUP_BACK_HEIGHT)) || m_nCurrExLayer == HOVEROPTION_BACK) { + m_nHoverOption = HOVEROPTION_BACK; + + } else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_LIST_LEFT - 10.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X + CONTSETUP_BOUND_COLUMN_WIDTH) + && m_nMousePosY > MENU_Y(CONTSETUP_LIST_TOP - 10.0f) && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_LIST_BOTTOM)) { + m_nHoverOption = HOVEROPTION_LIST; + + } else { + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + } + } + + // Back button and it's shadow + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); + CFont::SetRightJustifyOn(); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); + CFont::PrintString(MENU_X_RIGHT_ALIGNED(CONTSETUP_BACK_RIGHT - 2.0f), SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_BACK_BOTTOM - 4.0f), TheText.Get("FEDS_TB")); +} + +void +CMenuManager::DrawFrontEnd() +{ + CFont::SetAlphaFade(255.0f); + CSprite2d::InitPerFrame(); + CFont::InitPerFrame(); + SetFrontEndRenderStates(); + m_NoEmptyBinding = true; + + if (m_nCurrScreen == MENUPAGE_NONE) { + if (m_bGameNotLoaded) { + m_nCurrScreen = MENUPAGE_START_MENU; + } else { + m_nCurrScreen = MENUPAGE_PAUSE_MENU; + } + SETUP_SCROLLING(m_nCurrScreen) + } + + if (m_nCurrOption == 0 && aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL) + m_nCurrOption = 1; + + if (m_firstStartCounter == 255 && m_nMenuFadeAlpha == 255) + bMenuChangeOngoing = false; + + DrawBackground(false); +} + +void +CMenuManager::DrawBackground(bool transitionCall) +{ + if (!m_bSpritesLoaded) + return; + + SetFrontEndRenderStates(); + + if (m_firstStartCounter < 255) { + CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, 255)); + } + + if (m_nMenuFadeAlpha != 0) { + + if (m_nMenuFadeAlpha < 255) { + + menuBg.Translate(m_nMenuFadeAlpha); + SetFrontEndRenderStates(); + m_aFrontEndSprites[MENUSPRITE_BACKGROUND].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, FadeIn(255))); + if (m_nCurrScreen == MENUPAGE_MAP) + PrintMap(); + + // Left border + CSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(menuBg.bottomLeft_x), SCREEN_STRETCH_Y(menuBg.bottomLeft_y), 0.0f, SCREEN_HEIGHT, + SCREEN_STRETCH_X(menuBg.topLeft_x), SCREEN_STRETCH_Y(menuBg.topLeft_y), 0.0f, 0.0f, CRGBA(0, 0, 0, 255)); + + // Top border + CSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(menuBg.topRight_x), SCREEN_STRETCH_Y(menuBg.topRight_y), + SCREEN_STRETCH_X(menuBg.topLeft_x), SCREEN_STRETCH_Y(menuBg.topLeft_y), SCREEN_WIDTH, 0.0f, 0.0f, 0.0f, CRGBA(0, 0, 0, 255)); + + // Bottom border + CSprite2d::Draw2DPolygon(SCREEN_WIDTH, SCREEN_HEIGHT, 0.0f, SCREEN_HEIGHT, SCREEN_STRETCH_X(menuBg.bottomRight_x), SCREEN_STRETCH_Y(menuBg.bottomRight_y), + SCREEN_STRETCH_X(menuBg.bottomLeft_x), SCREEN_STRETCH_Y(menuBg.bottomLeft_y), CRGBA(0, 0, 0, 255)); + + // Right border + CSprite2d::Draw2DPolygon(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_STRETCH_X(menuBg.bottomRight_x), SCREEN_STRETCH_Y(menuBg.bottomRight_y), + SCREEN_WIDTH, 0.0f, SCREEN_STRETCH_X(menuBg.topRight_x), SCREEN_STRETCH_Y(menuBg.topRight_y), CRGBA(0, 0, 0, 255)); + } else { + m_nMenuFadeAlpha = 255; + m_firstStartCounter = 255; + m_aFrontEndSprites[MENUSPRITE_BACKGROUND].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, FadeIn(255))); + if (m_nCurrScreen == MENUPAGE_MAP) + PrintMap(); + + // Left border + CSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(menuBg.bottomLeft_x), SCREEN_STRETCH_Y(menuBg.bottomLeft_y), 0.0f, SCREEN_HEIGHT, + SCREEN_STRETCH_X(menuBg.topLeft_x), SCREEN_STRETCH_Y(menuBg.topLeft_y), 0.0f, 0.0f, CRGBA(0, 0, 0, 255)); + + // Top border + CSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(menuBg.topRight_x), SCREEN_STRETCH_Y(menuBg.topRight_y), + SCREEN_STRETCH_X(menuBg.topLeft_x), SCREEN_STRETCH_Y(menuBg.topLeft_y), SCREEN_WIDTH, 0.0f, 0.0f, 0.0f, CRGBA(0, 0, 0, 255)); + + // Bottom border + CSprite2d::Draw2DPolygon(SCREEN_WIDTH, SCREEN_HEIGHT, 0.0f, SCREEN_HEIGHT, SCREEN_STRETCH_X(menuBg.bottomRight_x), SCREEN_STRETCH_Y(menuBg.bottomRight_y), + SCREEN_STRETCH_X(menuBg.bottomLeft_x), SCREEN_STRETCH_Y(menuBg.bottomLeft_y), CRGBA(0, 0, 0, 255)); + + // Right border + CSprite2d::Draw2DPolygon(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_STRETCH_X(menuBg.bottomRight_x), SCREEN_STRETCH_Y(menuBg.bottomRight_y), + SCREEN_WIDTH, 0.0f, SCREEN_STRETCH_X(menuBg.topRight_x), SCREEN_STRETCH_Y(menuBg.topRight_y), CRGBA(0, 0, 0, 255)); + } + } else { + menuBg.SaveCurrentCoors(); + switch (m_nCurrScreen) { + case MENUPAGE_STATS: + menuBg.topLeft_x = 70.0f; + menuBg.topLeft_y = 75.0f; + menuBg.topRight_x = 550.0f; + menuBg.topRight_y = 16.0f; + menuBg.bottomLeft_x = 74.0f; + menuBg.bottomLeft_y = 354.0f; + menuBg.bottomRight_x = 581.0f; + menuBg.bottomRight_y = 340.0f; + break; + case MENUPAGE_SOUND_SETTINGS: + menuBg.topLeft_x = 26.0f; + menuBg.topLeft_y = 59.0f; + menuBg.topRight_x = 629.0f; + menuBg.topRight_y = 29.0f; + menuBg.bottomLeft_x = 15.0f; + menuBg.bottomLeft_y = 438.0f; + menuBg.bottomRight_x = 610.0f; + menuBg.bottomRight_y = 410.0f; + break; + case MENUPAGE_SKIN_SELECT: + case MENUPAGE_KEYBOARD_CONTROLS: + menuBg.topLeft_x = 14.0f; + menuBg.topLeft_y = 39.0f; + menuBg.topRight_x = 636.0f; + menuBg.topRight_y = 29.0f; + menuBg.bottomLeft_x = 15.0f; + menuBg.bottomLeft_y = 426.0f; + menuBg.bottomRight_x = 630.0f; + menuBg.bottomRight_y = 398.0f; + break; + case MENUPAGE_BRIEFS: + case MENUPAGE_DISPLAY_SETTINGS: + case MENUPAGE_MAP: + case MENUPAGE_CHOOSE_LOAD_SLOT: + case MENUPAGE_CHOOSE_DELETE_SLOT: + case MENUPAGE_CHOOSE_SAVE_SLOT: + case MENUPAGE_MOUSE_CONTROLS: + menuBg.topLeft_x = 26.0f; + menuBg.topLeft_y = 59.0f; + menuBg.topRight_x = 629.0f; + menuBg.topRight_y = 29.0f; + menuBg.bottomLeft_x = 15.0f; + menuBg.bottomLeft_y = 426.0f; + menuBg.bottomRight_x = 610.0f; + menuBg.bottomRight_y = 398.0f; + break; + default: +#ifdef CUSTOM_FRONTEND_OPTIONS + if (aScreens[m_nCurrScreen].layout && aScreens[m_nCurrScreen].layout->noInvasiveBorders) { + // Taken from the case above + menuBg.topLeft_x = 26.0f; + menuBg.topLeft_y = 59.0f; + menuBg.topRight_x = 629.0f; + menuBg.topRight_y = 29.0f; + menuBg.bottomLeft_x = 15.0f; + menuBg.bottomLeft_y = 426.0f; + menuBg.bottomRight_x = 610.0f; + menuBg.bottomRight_y = 398.0f; + break; + } +#endif + menuBg.topLeft_x = CGeneral::GetRandomNumber() % 40 + 65; + menuBg.topLeft_y = CGeneral::GetRandomNumber() % 40 + 21; + menuBg.topRight_x = CGeneral::GetRandomNumber() % 40 + 568; + menuBg.topRight_y = CGeneral::GetRandomNumber() % 40 + 44; + menuBg.bottomLeft_x = CGeneral::GetRandomNumber() % 40 + 36; + menuBg.bottomLeft_y = CGeneral::GetRandomNumber() % 40 + 382; + menuBg.bottomRight_x = CGeneral::GetRandomNumber() % 40 + 593; + menuBg.bottomRight_y = CGeneral::GetRandomNumber() % 40 + 342; + break; + } + + menuBg.UpdateMultipliers(); + if (m_firstStartCounter == 255) + m_nOptionHighlightTransitionBlend = 0; + } + + static PauseModeTime LastFade = 0; + + if (m_nMenuFadeAlpha < 255) { + static uint8 forceFadeInCounter = 0; + if (CTimer::GetTimeInMillisecondsPauseMode() - LastFade > 30 +#ifndef FIX_HIGH_FPS_BUGS_ON_FRONTEND // Dirty dirty hack + || forceFadeInCounter > 30 +#endif + ) { + m_nMenuFadeAlpha += 20; + if (m_firstStartCounter < 255) { + m_firstStartCounter = Min(m_firstStartCounter + 20, 255); + } + LastFade = CTimer::GetTimeInMillisecondsPauseMode(); + } + forceFadeInCounter++; + } else if (m_nMenuFadeAlpha > 255) + m_nMenuFadeAlpha = 255; + + if (!transitionCall && m_firstStartCounter == 255) { + int actualAlpha = m_nMenuFadeAlpha; + if (actualAlpha < 255) { + int actualScreen = m_nCurrScreen; + SetFrontEndRenderStates(); + m_nCurrScreen = m_nPrevScreen; + m_nMenuFadeAlpha = 255 - m_nMenuFadeAlpha; + switch (m_nCurrScreen) { + case MENUPAGE_SKIN_SELECT: + DrawPlayerSetupScreen(false); + break; + case MENUPAGE_KEYBOARD_CONTROLS: + DrawControllerSetupScreen(); + break; + case MENUPAGE_OUTRO: + DrawQuitGameScreen(); + break; + default: + DrawStandardMenus(false); + break; + } + m_nCurrScreen = actualScreen; + m_nMenuFadeAlpha = actualAlpha; + } + } + + switch (m_nCurrScreen) { + case MENUPAGE_SKIN_SELECT: + DrawPlayerSetupScreen(true); + break; + case MENUPAGE_KEYBOARD_CONTROLS: + DrawControllerSetupScreen(); + break; + case MENUPAGE_OUTRO: + DrawQuitGameScreen(); + break; + default: + DrawStandardMenus(true); + break; + } + + CFont::DrawFonts(); + SetFrontEndRenderStates(); + + if (m_nCurrScreen != MENUPAGE_OUTRO) + if (m_firstStartCounter == 255) { + m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(SCREEN_STRETCH_X(27.0f), MENU_Y(8.0f), SCREEN_STRETCH_X(27.0f) + MENU_X(130.f), MENU_Y(138.0f)), CRGBA(255, 255, 255, 255)); + } else { + m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(SCREEN_STRETCH_X(27.0f), MENU_Y(8.0f), SCREEN_STRETCH_X(27.0f) + MENU_X(130.f), MENU_Y(138.0f)), CRGBA(255, 255, 255, FadeIn(255))); + } + + if (m_ShowEmptyBindingError) { + static PauseModeTime lastBindingError = CTimer::GetTimeInMillisecondsPauseMode(); + static bool bindingErrorShown = false; + if (bindingErrorShown) { + lastBindingError = CTimer::GetTimeInMillisecondsPauseMode(); + bindingErrorShown = false; + } + SmallMessageScreen("FEC_ERI"); + CFont::DrawFonts(); + if (CTimer::GetTimeInMillisecondsPauseMode() - lastBindingError > 4000) { + m_ShowEmptyBindingError = false; + bindingErrorShown = true; + } + } + + if (m_bShowMouse) { + CRect mouse(0.0f, 0.0f, MENU_X(35.0f), MENU_Y(35.0f)); + CRect shad(MENU_X(10.0f), MENU_Y(3.0f), MENU_X(45.0f), MENU_Y(38.0f)); + + mouse.Translate(m_nMousePosX, m_nMousePosY); + shad.Translate(m_nMousePosX, m_nMousePosY); + m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); + m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); + } +} + +void +CMenuManager::DrawPlayerSetupScreen(bool activeScreen) +{ + RESET_FONT_FOR_NEW_PAGE + + // lstrcpy's changed with strcpy + if (!m_bSkinsEnumerated) { + OutputDebugString("Enumerating skin filenames from skins..."); + m_pSkinListHead.nextSkin = nil; + m_pSelectedSkin = &m_pSkinListHead; + m_pSelectedSkin->nextSkin = new tSkinInfo; + m_pSelectedSkin = m_pSelectedSkin->nextSkin; + m_pSelectedSkin->skinId = 0; + strcpy(m_pSelectedSkin->skinNameOriginal, DEFAULT_SKIN_NAME); + strcpy(m_pSelectedSkin->skinNameDisplayed, UnicodeToAscii(TheText.Get("FET_DSN"))); + int nextSkinId = 1; + m_pSelectedSkin->nextSkin = nil; + + WIN32_FIND_DATA FindFileData; + SYSTEMTIME SystemTime; + HANDLE handle = FindFirstFile("skins\\*.bmp", &FindFileData); + for (int i = 1; handle != INVALID_HANDLE_VALUE && i; i = FindNextFile(handle, &FindFileData)) { + if (strcmp(FindFileData.cFileName, DEFAULT_SKIN_NAME) != 0) { + m_pSelectedSkin->nextSkin = new tSkinInfo; + m_pSelectedSkin = m_pSelectedSkin->nextSkin; + m_pSelectedSkin->skinId = nextSkinId; + strcpy(m_pSelectedSkin->skinNameOriginal, FindFileData.cFileName); + strcpy(m_pSelectedSkin->skinNameDisplayed, FindFileData.cFileName); + FileTimeToSystemTime(&FindFileData.ftLastWriteTime, &SystemTime); + GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &SystemTime, 0, m_pSelectedSkin->date, 255); + ++nextSkinId; + m_pSelectedSkin->nextSkin = nil; + } + } + FindClose(handle); + m_nSkinsTotal = nextSkinId; + char nameTemp[256]; + for (m_pSelectedSkin = m_pSkinListHead.nextSkin; m_pSelectedSkin; m_pSelectedSkin = m_pSelectedSkin->nextSkin) { + // Drop extension + int oldLength = (int)strlen(m_pSelectedSkin->skinNameDisplayed); + m_pSelectedSkin->skinNameDisplayed[oldLength - 4] = '\0'; + m_pSelectedSkin->skinNameOriginal[oldLength - 4] = '\0'; + + // Fill to 40 bytes-39 chars, idk why. This is done in sepearate function in game. + strncpy(nameTemp, m_pSelectedSkin->skinNameDisplayed, 39); // game doesn't do that, but in our day strncpy to same string is forbidden + strncpy(m_pSelectedSkin->skinNameDisplayed, nameTemp, 39); + if (oldLength - 4 > 39) + m_pSelectedSkin->skinNameDisplayed[39] = '\0'; + + // Make string lowercase, except first letter + strlwr(m_pSelectedSkin->skinNameDisplayed); + strncpy(nameTemp, m_pSelectedSkin->skinNameDisplayed, 1); + strupr(nameTemp); + strncpy(m_pSelectedSkin->skinNameDisplayed, nameTemp, 1); + + // Change some chars +#ifdef FIX_BUGS + for (int k = 0; m_pSelectedSkin->skinNameDisplayed[k] != '\0'; ++k) { +#else + for (int k = 0; m_pSelectedSkin->skinNameOriginal[k] != '\0'; ++k) { +#endif + if (!strncmp(&m_pSelectedSkin->skinNameDisplayed[k], "_", 1)) + strncpy(&m_pSelectedSkin->skinNameDisplayed[k], " ", 1); + if (!strncmp(&m_pSelectedSkin->skinNameDisplayed[k], "@", 1)) + strncpy(&m_pSelectedSkin->skinNameDisplayed[k], " ", 1); + if (!strncmp(&m_pSelectedSkin->skinNameDisplayed[k], "{", 1)) + strncpy(&m_pSelectedSkin->skinNameDisplayed[k], "(", 1); + if (!strncmp(&m_pSelectedSkin->skinNameDisplayed[k], "}", 1)) + strncpy(&m_pSelectedSkin->skinNameDisplayed[k], ")", 1); + if (!strncmp(&m_pSelectedSkin->skinNameDisplayed[k], "£", 1)) + strncpy(&m_pSelectedSkin->skinNameDisplayed[k], "$", 1); + } + + // Make letters after whitespace uppercase + for (int l = 0; m_pSelectedSkin->skinNameDisplayed[l] != '\0'; ++l) { + if (!strncmp(&m_pSelectedSkin->skinNameDisplayed[l], " ", 1)) { + if (m_pSelectedSkin->skinNameDisplayed[l + 1]) { + strncpy(nameTemp, &m_pSelectedSkin->skinNameDisplayed[l + 1], 1); + strupr(nameTemp); + strncpy(&m_pSelectedSkin->skinNameDisplayed[l + 1], nameTemp, 1); + } + } + } + } + OutputDebugString("Finished enumerating skin files."); + m_bSkinsEnumerated = true; + } + CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT), MENU_Y(PLAYERSETUP_LIST_TOP), + MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)), CRGBA(LIST_BACKGROUND_COLOR.r, LIST_BACKGROUND_COLOR.g, LIST_BACKGROUND_COLOR.b, FadeIn(LIST_BACKGROUND_COLOR.a))); + + SET_FONT_FOR_MENU_HEADER + CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X) - MENU_X(7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get("FET_PS")); + + CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255))); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get("FET_PS")); + + // Header (Skin - Date) + if (m_nCurrExLayer == HOVEROPTION_LIST) { + CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255))); + } else { + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); + } + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT)); + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_DATE_COLUMN_RIGHT), MENU_Y(PLAYERSETUP_LIST_TOP), TheText.Get("FES_DAT")); + switch (m_PrefsLanguage) { + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + CFont::SetScale(MENU_X(0.6f), MENU_Y(MENUACTION_SCALE_MULT)); + break; + default: + CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT)); + break; + } + CFont::SetRightJustifyOff(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(PLAYERSETUP_SKIN_COLUMN_LEFT), MENU_Y(PLAYERSETUP_LIST_TOP), TheText.Get("FES_SKN")); + CFont::SetDropShadowPosition(0); + + // Skin list + SET_FONT_FOR_LIST_ITEM + if (m_nSkinsTotal > 0) { + for (m_pSelectedSkin = m_pSkinListHead.nextSkin; m_pSelectedSkin->skinId != m_nFirstVisibleRowOnList; + m_pSelectedSkin = m_pSelectedSkin->nextSkin); + + int rowTextY = PLAYERSETUP_LIST_BODY_TOP - 1; + int orderInVisibles = 0; + int rowEndY = PLAYERSETUP_LIST_BODY_TOP + PLAYERSETUP_ROW_HEIGHT + 1; + int rowStartY = PLAYERSETUP_LIST_BODY_TOP; + for (int rowIdx = m_nFirstVisibleRowOnList; + rowIdx < m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW && m_pSelectedSkin; ) { + + if (m_nMousePosX > MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT)) { + if (m_nMousePosY > MENU_Y(rowStartY) && m_nMousePosY < MENU_Y(rowEndY)) { + m_nOptionMouseHovering = rowIdx; + if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { + m_nCurrExLayer = HOVEROPTION_LIST; + } + if (m_nHoverOption == HOVEROPTION_SKIN) { + if (rowIdx == m_nSelectedListRow) { + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + if (m_nSkinsTotal > 0) { + strcpy(m_PrefsSkinFile, m_aSkinName); + CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); + SaveSettings(); + } + } else { + m_nCurrExLayer = HOVEROPTION_LIST; + m_nSelectedListRow = rowIdx; + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + } + } + } + } + + // Preview skin/change color of row when we focused on another row. + if (orderInVisibles == m_nSelectedListRow - m_nFirstVisibleRowOnList) { + CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); + static int lastSelectedSkin = -1; + if (m_nSelectedListRow != lastSelectedSkin) { + strcpy(m_aSkinName, m_pSelectedSkin->skinNameOriginal); + CWorld::Players[0].SetPlayerSkin(m_aSkinName); + } + lastSelectedSkin = m_nSelectedListRow; + } else if (!strcmp(m_PrefsSkinFile, m_pSelectedSkin->skinNameOriginal)) { + CFont::SetColor(CRGBA(255, 255, 155, FadeIn(255))); + } else { + CFont::SetColor(CRGBA(LIST_OPTION_COLOR.r, LIST_OPTION_COLOR.g, LIST_OPTION_COLOR.b, FadeIn(LIST_OPTION_COLOR.a))); + } + wchar unicodeTemp[80]; + AsciiToUnicode(m_pSelectedSkin->skinNameDisplayed, unicodeTemp); + CFont::SetRightJustifyOff(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(PLAYERSETUP_SKIN_COLUMN_LEFT), MENU_Y(rowTextY), unicodeTemp); + + // If not "Default skin" option + if (rowIdx != 0) { + char dateTemp[32]; + sprintf(dateTemp, "%s", m_pSelectedSkin->date); + AsciiToUnicode(dateTemp, unicodeTemp); + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_DATE_COLUMN_RIGHT), MENU_Y(rowTextY), unicodeTemp); + } + ++orderInVisibles; + rowEndY += PLAYERSETUP_ROW_HEIGHT; + rowStartY += PLAYERSETUP_ROW_HEIGHT; + rowTextY += PLAYERSETUP_ROW_HEIGHT; + ++rowIdx; + m_pSelectedSkin = m_pSelectedSkin->nextSkin; + } + // Scrollbar background - it's unchanged since III and still yellowish... + CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP), + MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBAR_WIDTH), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)), CRGBA(100, 100, 66, FadeIn(205))); + + float scrollbarHeight = SCROLLBAR_MAX_HEIGHT / (m_nSkinsTotal / (float) MAX_VISIBLE_LIST_ROW); + float scrollbarBottom, scrollbarTop; + if (m_nSkinsTotal <= MAX_VISIBLE_LIST_ROW) { + scrollbarBottom = SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 4.0f); + scrollbarTop = MENU_Y(PLAYERSETUP_LIST_BODY_TOP); + + // Scrollbar shadow + CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4), scrollbarTop, + MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 1 - PLAYERSETUP_SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)), CRGBA(50, 50, 50, FadeIn(255))); + } else { +#ifdef FIX_BUGS + scrollbarBottom = MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 8 + m_nScrollbarTopMargin + scrollbarHeight); + scrollbarTop = MENU_Y(PLAYERSETUP_LIST_BODY_TOP + m_nScrollbarTopMargin); +#else + scrollbarBottom = MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 4 + m_nScrollbarTopMargin + scrollbarHeight - SCROLLBAR_MAX_HEIGHT / m_nSkinsTotal); + scrollbarTop = MENU_Y(SCROLLBAR_MAX_HEIGHT / m_nSkinsTotal + PLAYERSETUP_LIST_BODY_TOP - 3 + m_nScrollbarTopMargin); +#endif + // Scrollbar shadow + CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4), scrollbarTop, + MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 1 - PLAYERSETUP_SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)), + CRGBA(50, 50, 50, FadeIn(255))); + + } + // Scrollbar + CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4), scrollbarTop, + MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH), scrollbarBottom), + CRGBA(SCROLLBAR_COLOR.r, SCROLLBAR_COLOR.g, SCROLLBAR_COLOR.b, FadeIn(255))); + + // FIX: Scroll button dimensions are buggy, because: + // 1 - stretches the original image + // 2 - leaves gap between button and scrollbar + if (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP) { +#ifdef FIX_BUGS + m_aFrontEndSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP), + MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), MENU_Y(PLAYERSETUP_LIST_TOP + PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), + CRGBA(255, 255, 255, FadeIn(255))); +#else + m_aFrontEndSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP), + MENU_X_RIGHT_ALIGNED(-20.0f), MENU_Y(PLAYERSETUP_LIST_TOP + 58)), + CRGBA(255, 255, 255, FadeIn(255))); +#endif + } else { +#ifdef FIX_BUGS + m_aFrontEndSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP), + MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), MENU_Y(PLAYERSETUP_LIST_TOP + PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), + CRGBA(255, 255, 255, FadeIn(255))); +#else + m_aFrontEndSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP), + MENU_X_RIGHT_ALIGNED(-21.0f), MENU_Y(PLAYERSETUP_LIST_TOP + 58)), + CRGBA(255, 255, 255, FadeIn(255))); +#endif + } + + if (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN) { +#ifdef FIX_BUGS + m_aFrontEndSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1), + MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), + CRGBA(255, 255, 255, FadeIn(255))); +#else + m_aFrontEndSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(141.0f), + MENU_X_RIGHT_ALIGNED(-20.0f), SCREEN_SCALE_FROM_BOTTOM(83.0f)), + CRGBA(255, 255, 255, FadeIn(255))); +#endif + } else { +#ifdef FIX_BUGS + m_aFrontEndSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1), + MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), + CRGBA(255, 255, 255, FadeIn(255))); +#else + m_aFrontEndSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(141.0f), + MENU_X_RIGHT_ALIGNED(-21.0f), SCREEN_SCALE_FROM_BOTTOM(83.0f)), + CRGBA(255, 255, 255, FadeIn(255))); +#endif + + } + if (activeScreen) + CPlayerSkin::RenderFrontendSkinEdit(); + + // Big apply button + if (strcmp(m_aSkinName, m_PrefsSkinFile) != 0) { + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + switch (m_PrefsLanguage) { + case LANGUAGE_FRENCH: + CFont::SetScale(MENU_X(1.1f), MENU_Y(1.9f)); + break; + case LANGUAGE_GERMAN: + CFont::SetScale(MENU_X(0.85f), MENU_Y(1.9f)); + break; + case LANGUAGE_ITALIAN: + case LANGUAGE_SPANISH: + CFont::SetScale(MENU_X(1.4f), MENU_Y(1.9f)); + break; + default: + CFont::SetScale(MENU_X(1.9f), MENU_Y(1.9f)); + break; + } + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(120))); + CFont::SetRightJustifyOff(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(24.0f), MENU_Y(220.0f), TheText.Get("FET_APP")); + } + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + + CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); + + if ((m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 1) - CFont::GetStringWidth(TheText.Get("FEDS_TB"), true) + && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 1) + && m_nMousePosY > SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 3) + && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 26)) + || m_nCurrExLayer == HOVEROPTION_BACK) { + + m_nHoverOption = HOVEROPTION_BACK; + } else if ((strcmp(m_aSkinName, m_PrefsSkinFile) != 0 + && m_nMousePosX > MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) + && m_nMousePosX < MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) + CFont::GetStringWidth(TheText.Get("FES_SET"), true) + && m_nMousePosY > SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 3) + && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 26)) + || m_nCurrExLayer == HOVEROPTION_USESKIN) { + + m_nHoverOption = HOVEROPTION_USESKIN; + } else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) + && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH - 2) + && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_TOP) + && m_nMousePosY < MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 3)) { + if (m_nHoverOption != HOVEROPTION_CLICKED_SCROLL_UP && m_nHoverOption != HOVEROPTION_CLICKED_SCROLL_DOWN) + m_nHoverOption = HOVEROPTION_OVER_SCROLL_UP; + + } else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) + && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH - 2) + && m_nMousePosY > SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1) + && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)) { + if (m_nHoverOption != HOVEROPTION_CLICKED_SCROLL_UP && m_nHoverOption != HOVEROPTION_CLICKED_SCROLL_DOWN) + m_nHoverOption = HOVEROPTION_OVER_SCROLL_DOWN; + + } else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) + && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH - 2) + && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 3) +#ifdef FIX_BUGS + && m_nMousePosY < MENU_Y(PLAYERSETUP_LIST_BODY_TOP + m_nScrollbarTopMargin)) { +#else + && m_nMousePosY < MENU_Y(SCROLLBAR_MAX_HEIGHT / m_nTotalListRow + PLAYERSETUP_LIST_BODY_TOP - 3 + m_nScrollbarTopMargin)) { +#endif + m_nHoverOption = HOVEROPTION_PAGEUP; + + } else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) + && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH - 2) +#ifdef FIX_BUGS + && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 8 + m_nScrollbarTopMargin + scrollbarHeight) +#else + && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 3 + m_nScrollbarTopMargin + scrollbarHeight - SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) +#endif + && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1)) { + m_nHoverOption = HOVEROPTION_PAGEDOWN; + + } else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4) + && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH) +#ifdef FIX_BUGS + && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP + m_nScrollbarTopMargin) + && m_nMousePosY < MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 8 + m_nScrollbarTopMargin + scrollbarHeight)) { +#else + && m_nMousePosY > MENU_Y(SCROLLBAR_MAX_HEIGHT / m_nTotalListRow + PLAYERSETUP_LIST_BODY_TOP - 3 + m_nScrollbarTopMargin) + && m_nMousePosY < MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 3 + m_nScrollbarTopMargin + scrollbarHeight - SCROLLBAR_MAX_HEIGHT / m_nTotalListRow)) { +#endif + m_nHoverOption = HOVEROPTION_HOLDING_SCROLLBAR; + + } else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT) + && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP + 1) && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)) { + m_nHoverOption = HOVEROPTION_LIST; + + } else { + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + } + } + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); + CFont::SetRightJustifyOn(); + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); + + // Back button + CFont::PrintString(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 5), TheText.Get("FEDS_TB")); + CFont::SetRightJustifyOff(); + + if (!strcmp(m_aSkinName, m_PrefsSkinFile)) { + CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); + } else { + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); + } + + // Use skin button + CFont::PrintString(MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 5), TheText.Get("FES_SET")); + CFont::SetDropShadowPosition(0); +} + +int +CMenuManager::FadeIn(int alpha) +{ + return Min(m_nMenuFadeAlpha, alpha); +} + +int +CMenuManager::GetStartOptionsCntrlConfigScreens() +{ + int number = 0; + switch (m_nCurrScreen) { +#ifdef LEGACY_MENU_OPTIONS + case MENUPAGE_CONTROLLER_PC_OLD3: + number = 34; + break; + case MENUPAGE_CONTROLLER_DEBUG: + number = 35; + break; +#endif + case MENUPAGE_KEYBOARD_CONTROLS: + number = 0; + break; + default: + break; + } + return number; +} + +void +CMenuManager::InitialiseChangedLanguageSettings() +{ + if (m_bFrontEnd_ReloadObrTxtGxt) { + m_bFrontEnd_ReloadObrTxtGxt = false; + CTimer::Stop(); + TheText.Unload(); + TheText.Load(); + CTimer::Update(); + CGame::frenchGame = false; + CGame::germanGame = false; +#ifdef MORE_LANGUAGES + CGame::russianGame = false; + CGame::japaneseGame = false; + switch (m_PrefsLanguage) { + case LANGUAGE_POLISH: + CFont::ReloadFonts(FONT_LANGSET_POLISH); + break; + case LANGUAGE_RUSSIAN: + CFont::ReloadFonts(FONT_LANGSET_RUSSIAN); + break; + case LANGUAGE_JAPANESE: + CFont::ReloadFonts(FONT_LANGSET_JAPANESE); + break; + default: + CFont::ReloadFonts(FONT_LANGSET_EFIGS); + break; + } +#endif + + switch (m_PrefsLanguage) { + case LANGUAGE_FRENCH: + CGame::frenchGame = true; + break; + case LANGUAGE_GERMAN: + CGame::germanGame = true; + break; +#ifdef MORE_LANGUAGES + case LANGUAGE_RUSSIAN: + CGame::russianGame = true; + break; + case LANGUAGE_JAPANESE: + CGame::japaneseGame = true; + break; +#endif + default: + break; + } + + } +} + +void +CMenuManager::LoadAllTextures() +{ + if (m_bSpritesLoaded) + return; + + // First icon is hidden behind arrow + m_LeftMostRadioX = MENU_X_LEFT_ALIGNED(MENURADIO_ICON_FIRST_X - MENURADIO_ICON_SIZE); + CTimer::Stop(); + + CStreaming::MakeSpaceFor(350 * CDSTREAM_SECTOR_SIZE); // twice of it in mobile + CStreaming::ImGonnaUseStreamingMemory(); + CGame::TidyUpMemory(false, true); + CTxdStore::PushCurrentTxd(); + int frontendTxdSlot1 = CTxdStore::FindTxdSlot("frontend1"); + + if(frontendTxdSlot1 == -1) + frontendTxdSlot1 = CTxdStore::AddTxdSlot("frontend1"); + + printf("LOAD frontend1\n"); + CTxdStore::LoadTxd(frontendTxdSlot1, "MODELS/FRONTEN1.TXD"); + CTxdStore::AddRef(frontendTxdSlot1); + CTxdStore::SetCurrentTxd(frontendTxdSlot1); + + for (int i = 0; i < 3; i++) { + m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]); + m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); + } + + CTxdStore::PopCurrentTxd(); + CStreaming::IHaveUsedStreamingMemory(); + + if (!m_OnlySaveMenu) { + CStreaming::MakeSpaceFor(692 * CDSTREAM_SECTOR_SIZE); // twice of it in mobile + CStreaming::ImGonnaUseStreamingMemory(); + CTxdStore::PushCurrentTxd(); + + int frontendTxdSlot2 = CTxdStore::FindTxdSlot("frontend2"); + + if (frontendTxdSlot2 == -1) + frontendTxdSlot2 = CTxdStore::AddTxdSlot("frontend2"); + + printf("LOAD frontend2\n"); + CTxdStore::LoadTxd(frontendTxdSlot2, "MODELS/FRONTEN2.TXD"); + CTxdStore::AddRef(frontendTxdSlot2); + CTxdStore::SetCurrentTxd(frontendTxdSlot2); + +#ifdef GAMEPAD_MENU + for (int i = 3; i < MENUSPRITE_CONTROLLER; i++) { +#else + for (int i = 3; i < NUM_MENU_SPRITES; i++) { +#endif + m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]); + m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); + } + + CTxdStore::PopCurrentTxd(); +#ifdef GAMEPAD_MENU + LoadController(m_PrefsControllerType); +#endif + CStreaming::IHaveUsedStreamingMemory(); + } + + m_bSpritesLoaded = true; + CTimer::Update(); +} + +void +CMenuManager::LoadSettings() +{ + CFileMgr::SetDirMyDocuments(); + int fileHandle = CFileMgr::OpenFile("gta_vc.set", "r"); + + int32 prevLang = m_PrefsLanguage; + MousePointerStateHelper.bInvertVertically = true; + CMBlur::BlurOn = false; + + // 50 is silly + char headerText[50]; + int someVersion = 0; + bool fileIsValid = true; + + if (fileHandle) { + CFileMgr::Read(fileHandle, headerText, 29); + + if (strncmp(headerText, TopLineEmptyFile, sizeof(TopLineEmptyFile) - 1) == 0) { + fileIsValid = false; + } else { + CFileMgr::Seek(fileHandle, 0, 0); + CFileMgr::Read(fileHandle, (char*)&someVersion, sizeof(someVersion)); + } + if (fileIsValid && someVersion >= 3) { + ControlsManager.LoadSettings(fileHandle); +#ifdef IMPROVED_VIDEOMODE + CFileMgr::Read(fileHandle, (char*)&m_nPrefsWidth, sizeof(m_nPrefsWidth)); + CFileMgr::Read(fileHandle, (char*)&m_nPrefsHeight, sizeof(m_nPrefsHeight)); + CFileMgr::Read(fileHandle, (char*)&m_nPrefsDepth, sizeof(m_nPrefsDepth)); + CFileMgr::Read(fileHandle, (char*)&m_nPrefsWindowed, sizeof(m_nPrefsWindowed)); + CFileMgr::Read(fileHandle, (char*)&m_nPrefsSubsystem, sizeof(m_nPrefsSubsystem)); + if(m_nPrefsWindowed != 0 && m_nPrefsWindowed != 1){ + // garbage data from vanilla settings file + // let skeleton find something + m_nPrefsWidth = 0; + m_nPrefsHeight = 0; + m_nPrefsDepth = 0; + m_nPrefsWindowed = 0; + m_nPrefsSubsystem = 0; + } + m_nSelectedScreenMode = m_nPrefsWindowed; +#else + CFileMgr::Read(fileHandle, gString, 20); +#endif + CFileMgr::Read(fileHandle, gString, 20); + CFileMgr::Read(fileHandle, gString, 4); + CFileMgr::Read(fileHandle, gString, 4); + CFileMgr::Read(fileHandle, gString, 1); +#ifdef LEGACY_MENU_OPTIONS + CFileMgr::Read(fileHandle, (char*)&m_PrefsVsyncDisp, 1); + CFileMgr::Read(fileHandle, (char*)&CMBlur::BlurOn, 1); +#else + CFileMgr::Read(fileHandle, gString, 1); + CFileMgr::Read(fileHandle, gString, 1); +#endif + CFileMgr::Read(fileHandle, (char*)&TheCamera.m_bHeadBob, 1); + CFileMgr::Read(fileHandle, (char*)&TheCamera.m_fMouseAccelHorzntl, 4); + CFileMgr::Read(fileHandle, (char*)&MousePointerStateHelper.bInvertVertically, 1); + CFileMgr::Read(fileHandle, (char*)&CVehicle::m_bDisableMouseSteering, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsSfxVolume, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsMusicVolume, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsMP3BoostVolume, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsRadioStation, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsSpeakers, 1); + CFileMgr::Read(fileHandle, (char*)&m_nPrefsAudio3DProviderIndex, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsDMA, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsBrightness, 2); + CFileMgr::Read(fileHandle, (char*)&m_PrefsLOD, sizeof(m_PrefsLOD)); + CFileMgr::Read(fileHandle, (char*)&m_PrefsShowSubtitles, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsUseWideScreen, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsFrameLimiter, 1); + CFileMgr::Read(fileHandle, (char*)&m_nDisplayVideoMode, 1); + CFileMgr::Read(fileHandle, m_PrefsSkinFile, 256); + CFileMgr::Read(fileHandle, (char*)&m_ControlMethod, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsLanguage, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsShowHud, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsRadarMode, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsShowLegends, 1); + } + } + + CFileMgr::CloseFile(fileHandle); + CFileMgr::SetDir(""); + +#ifdef LOAD_INI_SETTINGS + if (LoadINISettings()) { + LoadINIControllerSettings(); + } + // if no reVC.ini, create it, or update it with new values + SaveINISettings(); + SaveINIControllerSettings(); +#endif + +#ifdef FIX_BUGS + TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl + 0.0005f; +#endif +#ifdef PC_PLAYER_CONTROLS + CCamera::m_bUseMouse3rdPerson = m_ControlMethod == CONTROL_STANDARD; +#endif +#ifdef LEGACY_MENU_OPTIONS + m_PrefsVsync = m_PrefsVsyncDisp; +#endif + CRenderer::ms_lodDistScale = m_PrefsLOD; + + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER) + m_nPrefsAudio3DProviderIndex = -2; + + m_lastWorking3DAudioProvider = m_nPrefsAudio3DProviderIndex; + + if (m_PrefsLanguage == prevLang) + m_bLanguageLoaded = false; + else { + m_bLanguageLoaded = true; + TheText.Unload(); + TheText.Load(); + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + + OutputDebugString("The previously saved language is now in use"); + } + + WIN32_FIND_DATA FindFileData; + char skinfile[256+16]; // Stack analysis shows 16 bits gap, but I don't trust it. It may very well be MAX_PATH(260). + bool SkinFound = false; + HANDLE handle = FindFirstFile("skins\\*.bmp", &FindFileData); + for (int i = 1; handle != INVALID_HANDLE_VALUE && i; i = FindNextFile(handle, &FindFileData)) { + strcpy(skinfile, m_PrefsSkinFile); + strcat(skinfile, ".bmp"); + if (strcmp(FindFileData.cFileName, skinfile) == 0) + SkinFound = true; + } + FindClose(handle); + + if (!SkinFound) { + OutputDebugString("Default skin set as no other skins are available OR saved skin not found!"); + strcpy(m_PrefsSkinFile, DEFAULT_SKIN_NAME); + strcpy(m_aSkinName, DEFAULT_SKIN_NAME); + } +} + +void +CMenuManager::SaveSettings() +{ +#ifndef LOAD_INI_SETTINGS + static char RubbishString[48] = "stuffmorestuffevenmorestuff etc"; +#ifdef BIND_VEHICLE_FIREWEAPON + static int SomeVersion = 4; +#else + static int SomeVersion = 3; +#endif + + CFileMgr::SetDirMyDocuments(); + + int fileHandle = CFileMgr::OpenFile("gta_vc.set", "w+"); + if (fileHandle) { + CFileMgr::Write(fileHandle, (char*)&SomeVersion, sizeof(SomeVersion)); + ControlsManager.SaveSettings(fileHandle); +#ifdef IMPROVED_VIDEOMODE + CFileMgr::Write(fileHandle, (char*)&m_nPrefsWidth, sizeof(m_nPrefsWidth)); + CFileMgr::Write(fileHandle, (char*)&m_nPrefsHeight, sizeof(m_nPrefsHeight)); + CFileMgr::Write(fileHandle, (char*)&m_nPrefsDepth, sizeof(m_nPrefsDepth)); + CFileMgr::Write(fileHandle, (char*)&m_nPrefsWindowed, sizeof(m_nPrefsWindowed)); + CFileMgr::Write(fileHandle, (char*)&m_nPrefsSubsystem, sizeof(m_nPrefsSubsystem)); +#else + CFileMgr::Write(fileHandle, RubbishString, 20); +#endif + CFileMgr::Write(fileHandle, RubbishString, 20); + CFileMgr::Write(fileHandle, RubbishString, 4); + CFileMgr::Write(fileHandle, RubbishString, 4); + CFileMgr::Write(fileHandle, RubbishString, 1); +#ifdef LEGACY_MENU_OPTIONS + CFileMgr::Write(fileHandle, (char*)&m_PrefsVsyncDisp, 1); + CFileMgr::Write(fileHandle, (char*)&CMBlur::BlurOn, 1); +#else + CFileMgr::Write(fileHandle, RubbishString, 1); + CFileMgr::Write(fileHandle, RubbishString, 1); +#endif + CFileMgr::Write(fileHandle, (char*)&TheCamera.m_bHeadBob, 1); + CFileMgr::Write(fileHandle, (char*)&TheCamera.m_fMouseAccelHorzntl, 4); + CFileMgr::Write(fileHandle, (char*)&MousePointerStateHelper.bInvertVertically, 1); + CFileMgr::Write(fileHandle, (char*)&CVehicle::m_bDisableMouseSteering, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsSfxVolume, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsMusicVolume, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsMP3BoostVolume, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsRadioStation, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsSpeakers, 1); + CFileMgr::Write(fileHandle, (char*)&m_nPrefsAudio3DProviderIndex, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsDMA, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsBrightness, 2); + CFileMgr::Write(fileHandle, (char*)&m_PrefsLOD, sizeof(m_PrefsLOD)); + CFileMgr::Write(fileHandle, (char*)&m_PrefsShowSubtitles, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsUseWideScreen, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsFrameLimiter, 1); + CFileMgr::Write(fileHandle, (char*)&m_nPrefsVideoMode, 1); + CFileMgr::Write(fileHandle, m_PrefsSkinFile, 256); + CFileMgr::Write(fileHandle, (char*)&m_ControlMethod, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsLanguage, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsShowHud, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsRadarMode, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsShowLegends, 1); + } + m_lastWorking3DAudioProvider = m_nPrefsAudio3DProviderIndex; + + CFileMgr::CloseFile(fileHandle); + CFileMgr::SetDir(""); + +#else + m_lastWorking3DAudioProvider = m_nPrefsAudio3DProviderIndex; + SaveINISettings(); +#endif +} + +void +CMenuManager::MessageScreen(const char *text, bool blackBg) +{ + CSprite2d *splash = LoadSplash(nil); + if (!DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255)) + return; + + CSprite2d::SetRecipNearClip(); + CSprite2d::InitPerFrame(); + CFont::InitPerFrame(); + DefinedState(); + // CRGBA unused(255, 255, 255, 255); + if (blackBg) { + CSprite2d::DrawRect(CRect(0, SCREEN_HEIGHT, SCREEN_WIDTH, 0), CRGBA(0, 0, 0, 255)); + } + + m_nMenuFadeAlpha = 255; + SmallMessageScreen(text); + CFont::DrawFonts(); + DoRWStuffEndOfFrame(); +} + +void +CMenuManager::SmallMessageScreen(const char* text) +{ + CFont::SetBackgroundOff(); + CFont::SetPropOn(); + CFont::SetJustifyOn(); + CFont::SetBackGroundOnlyTextOn(); + CSprite2d::DrawRect(CRect(SCREEN_STRETCH_X(95.0f), SCREEN_SCALE_FROM_BOTTOM(165.0f), SCREEN_STRETCH_FROM_RIGHT(95.0f), SCREEN_SCALE_Y(115.0f)), CRGBA(50, 50, 50, FadeIn(210))); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetCentreSize(SCREEN_SCALE_X(430.0f)); + CFont::SetCentreOn(); + CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + CFont::SetScale(SCREEN_SCALE_X(SMALLTEXT_X_SCALE), SCREEN_SCALE_Y(SMALLTEXT_Y_SCALE)); + + int numOfLines = CFont::GetNumberLines(SCREEN_WIDTH / 2.f, SCREEN_SCALE_Y(135.f), TheText.Get(text)); + float y; + if (numOfLines > 1) + y = SCREEN_SCALE_Y(192.f) - numOfLines * SCREEN_SCALE_Y(8.f); + else + y = SCREEN_SCALE_Y(182.f); + + CFont::PrintString(SCREEN_WIDTH / 2.f, y, TheText.Get(text)); +} + +void +CMenuManager::PrintBriefs() +{ + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetRightJustifyOff(); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetScale(MENU_X(MEDIUMTEXT_X_SCALE), MENU_Y(MEDIUMTEXT_Y_SCALE)); + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(80.0f)); + CFont::SetDropShadowPosition(0); + + float nextY = BRIEFS_BOTTOM_MARGIN; + for (int i = 4; i >= 0; i--) { + if (nextY < BRIEFS_TOP_MARGIN) + break; + + tPreviousBrief &brief = CMessages::PreviousBriefs[i]; + if (brief.m_pText) { + CMessages::InsertNumberInString(brief.m_pText, + brief.m_nNumber[0], brief.m_nNumber[1], + brief.m_nNumber[2], brief.m_nNumber[3], + brief.m_nNumber[4], brief.m_nNumber[5], gUString); + CMessages::InsertStringInString(gUString, brief.m_pString); + CMessages::InsertPlayerControlKeysInString(gUString); + CFont::FilterOutTokensFromString(gUString); + + nextY -= CFont::GetNumberLines(MENU_X_LEFT_ALIGNED(BRIEFS_LINE_X), nextY, gUString) * BRIEFS_LINE_HEIGHT + BRIEFS_LINE_SPACING; + CFont::PrintString(MENU_X_LEFT_ALIGNED(BRIEFS_LINE_X), MENU_Y(nextY), gUString); + } + } +} + +void +CMenuManager::PrintStats() +{ +#ifdef SECUROM + static uint8 statsPirateCheck = 0; +#endif + static float scrollY = 0; + + int rowNum = CStats::ConstructStatLine(99999); + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(90.0f), MENU_Y(142.0f), + MENU_X_LEFT_ALIGNED(543.0f), MENU_Y(142.f), + MENU_X_LEFT_ALIGNED(107.0f), MENU_Y(316.f), + MENU_X_LEFT_ALIGNED(531.f), MENU_Y(299.f), CRGBA(LIST_BACKGROUND_COLOR.r, LIST_BACKGROUND_COLOR.g, LIST_BACKGROUND_COLOR.b, FadeIn(LIST_BACKGROUND_COLOR.a))); + + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetPropOn(); + CFont::SetDropShadowPosition(0); + +#ifdef SECUROM + if (statsPirateCheck == 0) + // if not pirated game + // statsPirateCheck = 46; + // else + statsPirateCheck = 45; +#endif + + if (m_PrefsLanguage == LANGUAGE_AMERICAN) + CFont::SetScale(MENU_X(0.43f), MENU_Y(0.75f)); + else + CFont::SetScale(MENU_X(0.37f), MENU_Y(0.75f)); + + static PauseModeTime lastCheck = 0; + + if (CTimer::GetTimeInMillisecondsPauseMode() - lastCheck > 40) { + + if (m_StatsScrollSpeed > 0.f) { + if (m_StatsScrollDirection == 0) + scrollY -= MENU_Y(100.f) / m_StatsScrollSpeed; + else + scrollY += MENU_Y(100.f) / m_StatsScrollSpeed; + } + lastCheck = CTimer::GetTimeInMillisecondsPauseMode(); + } + +#ifdef SECUROM + if (statsPirateCheck == 45) + return; +#endif + + float nextYChange, y, alpha; + + float totalHeight = (rowNum + 7) * STATS_ROW_HEIGHT; + for (int row = 0; row < rowNum; ++row) { + // Put faded away text at the top back to the bottom, in circular fashion + for (y = MENU_Y(STATS_ROW_HEIGHT) * row + MENU_Y(100.f) - scrollY; MENU_Y(STATS_FADING_AREA_LENGTH) > y; y += nextYChange) { + nextYChange = MENU_Y(totalHeight); + } + + // Put faded away text at the bottom back to the top + while (SCREEN_SCALE_FROM_BOTTOM(STATS_FADING_AREA_LENGTH) < y) { + y -= MENU_Y(totalHeight); + } + alpha = 0.f; + + // If it's still on screen + if (y > MENU_Y(STATS_VISIBLE_START_Y) && y < MENU_Y(STATS_VISIBLE_END_Y)) { + CStats::ConstructStatLine(row); + + // But about to dim from bottom + if (y < MENU_Y(STATS_BOTTOM_Y)) { + if (y > MENU_Y(STATS_BOTTOM_Y - STATS_FADING_AREA_LENGTH)) + alpha = (MENU_Y(STATS_BOTTOM_Y) - y) * 5.f; + } + + // About to dim from top + if (y > MENU_Y(STATS_TOP_Y)) { + if (y < MENU_Y(STATS_TOP_Y + STATS_FADING_AREA_LENGTH)) + alpha = (y - MENU_Y(STATS_TOP_Y)) * 5.f; + } + + // Content + if (y >= MENU_Y(STATS_TOP_Y + STATS_FADING_AREA_LENGTH) && y <= MENU_Y(STATS_BOTTOM_Y - STATS_FADING_AREA_LENGTH)) + alpha = 255.0f; + + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(Min(255.f, alpha)))); + CFont::SetRightJustifyOff(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(STATS_ROW_LEFT_MARGIN), y, gUString); + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_RIGHT_ALIGNED(STATS_ROW_RIGHT_MARGIN), y, gUString2); + } + } + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetCentreOn(); + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(0.65f), MENU_Y(1.05f)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(STATS_RATING_X), MENU_Y(STATS_RATING_Y_1), TheText.Get("CRIMRA")); + + CFont::SetCentreOff(); + CFont::SetRightJustifyOff(); + + // FIX: Game does that in a weird way, alignment and spacing is now ok + + sprintf(gString, "(%d)", CStats::FindCriminalRatingNumber()); + AsciiToUnicode(gString, gUString); + + UnicodeStrcpy(gUString2, CStats::FindCriminalRatingString()); + UnicodeStrcat(gUString2, gUString); + + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); +#ifndef FIX_BUGS + CFont::SetScale(MENU_X(0.5f), MENU_Y(0.9f)); +#else + CFont::SetScale(MENU_X(SMALLTEXT_X_SCALE), MENU_Y(SMALLTEXT_Y_SCALE)); +#endif + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetDropShadowPosition(0); + + CFont::PrintString(MENU_X_LEFT_ALIGNED(STATS_RATING_X) - CFont::GetStringWidth(gUString2, true) / 2.f, MENU_Y(STATS_RATING_Y_2), gUString2); +} + +void +CMenuManager::Process(void) +{ +#ifdef XBOX_MESSAGE_SCREEN + ProcessDialogTimer(); +#endif + + if (TheCamera.GetScreenFadeStatus() != FADE_0) + return; + + InitialiseChangedLanguageSettings(); + + if (m_bMenuActive) { + UserInput(); + ProcessFileActions(); + DMAudio.Service(); +#ifdef USE_TEXTURE_POOL + // TODO +#endif + } + + SwitchMenuOnAndOff(); +} + +#ifdef MAP_ENHANCEMENTS +#define ZOOM(x, y, in) \ + do { \ + if(m_fMapSize >= MENU_Y(1000.0f) && in) \ + break; \ + float z2 = in? 1.1f : 1.f/1.1f; \ + m_fMapCenterX += (x - m_fMapCenterX) * (1.0f - z2); \ + m_fMapCenterY += (y - m_fMapCenterY) * (1.0f - z2); \ + \ + if (m_fMapSize <= MENU_Y(MAP_MIN_SIZE) && !in) \ + break; \ + \ + m_fMapSize *= z2; \ + m_fMapCenterX = clamp(m_fMapCenterX, SCREEN_WIDTH/2 - (m_fMapSize - MENU_X(MAP_MIN_SIZE)), m_fMapSize - MENU_X(MAP_MIN_SIZE) + SCREEN_WIDTH/2); \ + m_fMapCenterY = clamp(m_fMapCenterY, SCREEN_HEIGHT/2 - (m_fMapSize - MENU_Y(MAP_MIN_SIZE)), m_fMapSize - MENU_Y(MAP_MIN_SIZE) + SCREEN_HEIGHT/2); \ + } while(0) + +#endif + +// Handles Map, Audio and Stats +void +CMenuManager::AdditionalOptionInput(bool &goBack) +{ + switch (m_nCurrScreen) { + case MENUPAGE_MAP: + { + static PauseModeTime lastMapTick = 0; + + // FIX: All those macros were hardcoded values originally. + +#ifndef MAP_ENHANCEMENTS + if (CPad::GetPad(0)->GetMouseWheelUpJustDown() || CPad::GetPad(0)->GetMouseWheelUpJustUp() || CPad::GetPad(0)->GetPageUp() || CPad::GetPad(0)->GetRightShoulder1()) { + if (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) { + m_fMapSize = Min(MENU_Y(1000.0f), m_fMapSize + MENU_Y(15.f)); + } + } + if (CPad::GetPad(0)->GetMouseWheelDownJustDown() || CPad::GetPad(0)->GetMouseWheelDownJustUp() || CPad::GetPad(0)->GetPageDown() || CPad::GetPad(0)->GetRightShoulder2()) { + if (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) { + if (m_fMapSize > MENU_Y(MAP_MIN_SIZE)) { + if (m_fMapCenterY > SCREEN_HEIGHT/2) + m_fMapCenterY -= (m_fMapCenterY - SCREEN_HEIGHT/2) / ((m_fMapSize - MENU_Y(MAP_MIN_SIZE)) * 1/15.f); + + if (m_fMapCenterY < SCREEN_HEIGHT/2) + m_fMapCenterY += (SCREEN_HEIGHT/2 - m_fMapCenterY) / ((m_fMapSize - MENU_Y(MAP_MIN_SIZE)) * 1/15.f); + + if (m_fMapCenterX > SCREEN_WIDTH/2) + m_fMapCenterX -= (m_fMapCenterX - SCREEN_WIDTH/2) / ((m_fMapSize - MENU_X(MAP_MIN_SIZE)) * 1/15.f); + + if (m_fMapCenterX < SCREEN_WIDTH/2) + m_fMapCenterX += (SCREEN_WIDTH/2 - m_fMapCenterX) / ((m_fMapSize - MENU_X(MAP_MIN_SIZE)) * 1/15.f); + + m_fMapSize = Max(MENU_Y(MAP_MIN_SIZE), m_fMapSize - MENU_Y(15.f)); + m_fMapCenterX = clamp(m_fMapCenterX, SCREEN_WIDTH/2 - (m_fMapSize - MENU_X(MAP_MIN_SIZE)), m_fMapSize - MENU_X(MAP_MIN_SIZE) + SCREEN_WIDTH/2); + m_fMapCenterY = clamp(m_fMapCenterY, SCREEN_HEIGHT/2 - (m_fMapSize - MENU_Y(MAP_MIN_SIZE)), m_fMapSize - MENU_Y(MAP_MIN_SIZE) + SCREEN_HEIGHT/2); + } else { + m_fMapSize = MENU_Y(MAP_MIN_SIZE); + } + } + } +#else + // Adding marker + if (m_nMenuFadeAlpha == 255) { + if (CPad::GetPad(0)->GetRightMouseJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { + if (mapCrosshair.y > m_fMapCenterY - m_fMapSize && mapCrosshair.y < m_fMapCenterY + m_fMapSize && + mapCrosshair.x > m_fMapCenterX - m_fMapSize && mapCrosshair.x < m_fMapCenterX + m_fMapSize) { + + // Don't ask me the meanings, I don't know. Found them by trying + float diffX = m_fMapCenterX - m_fMapSize, diffY = m_fMapCenterY - m_fMapSize; + float x = ((mapCrosshair.x - diffX) / (m_fMapSize * 2)) * (WORLD_SIZE_X / MENU_MAP_WIDTH_SCALE) - (WORLD_SIZE_X / 2 + MENU_MAP_LEFT_OFFSET * MENU_MAP_LENGTH_UNIT); + float y = (WORLD_SIZE_Y / 2 - MENU_MAP_TOP_OFFSET * MENU_MAP_LENGTH_UNIT) - ((mapCrosshair.y - diffY) / (m_fMapSize * 2)) * (WORLD_SIZE_Y / MENU_MAP_HEIGHT_SCALE); + CRadar::ToggleTargetMarker(x, y); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0); + } + } + } + + if (CPad::GetPad(0)->GetMouseWheelDown() || CPad::GetPad(0)->GetPageDown() || CPad::GetPad(0)->GetRightShoulder2()) { + if (CPad::GetPad(0)->GetMouseWheelDown() && m_fMapSize > MENU_X(MAP_SIZE_TO_ALLOW_X_MOVE)) + ZOOM(mapCrosshair.x, mapCrosshair.y, false); + else + ZOOM(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, false); + + } else if (CPad::GetPad(0)->GetMouseWheelUp() || CPad::GetPad(0)->GetPageUp() || CPad::GetPad(0)->GetRightShoulder1()) { + if (CPad::GetPad(0)->GetMouseWheelUp()) + ZOOM(mapCrosshair.x, mapCrosshair.y, true); + else + ZOOM(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, true); + } + + static bool justResetPointer = false; + if (CPad::GetPad(0)->GetLeftMouse()) { + if (!justResetPointer) { + m_fMapCenterX += m_nMousePosX - m_nMouseOldPosX; + m_fMapCenterY += m_nMousePosY - m_nMouseOldPosY; + m_fMapCenterX = clamp(m_fMapCenterX, SCREEN_WIDTH/2 - (m_fMapSize - MENU_X(MAP_MIN_SIZE)), m_fMapSize - MENU_X(MAP_MIN_SIZE) + SCREEN_WIDTH/2); + m_fMapCenterY = clamp(m_fMapCenterY, SCREEN_HEIGHT/2 - (m_fMapSize - MENU_Y(MAP_MIN_SIZE)), m_fMapSize - MENU_Y(MAP_MIN_SIZE) + SCREEN_HEIGHT/2); + } + justResetPointer = false; + + } else +#undef ZOOM +#endif + + { + // This is else block of GetLeftMouse() if MAP_ENHANCEMENTS defined, so all of GetLeftMouse() conditions below being rendered useless. + + if (CPad::GetPad(0)->GetLeftMouse() && m_nMousePosY < m_nMouseOldPosY || CPad::GetPad(0)->GetUp() || + CPad::GetPad(0)->GetDPadUp() || CPad::GetPad(0)->GetAnalogueUpDown() < 0) { + if (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) { + if ((m_fMapSize - MENU_Y(MAP_MIN_SIZE)) + SCREEN_HEIGHT/2 > m_fMapCenterY) + m_fMapCenterY += MENU_Y(15.f); + m_bShowMouse = false; + } + } + + if (CPad::GetPad(0)->GetLeftMouse() && m_nMousePosY > m_nMouseOldPosY || CPad::GetPad(0)->GetDown() || + CPad::GetPad(0)->GetDPadDown() || CPad::GetPad(0)->GetAnalogueUpDown() > 0) { + if (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) { + if (SCREEN_HEIGHT/2 - (m_fMapSize - MENU_Y(MAP_MIN_SIZE)) < m_fMapCenterY) + m_fMapCenterY -= MENU_Y(15.f); + m_bShowMouse = false; + } + } + + if (CPad::GetPad(0)->GetLeftMouse() && m_nMousePosX < m_nMouseOldPosX || CPad::GetPad(0)->GetLeft() || + CPad::GetPad(0)->GetDPadLeft() || CPad::GetPad(0)->GetAnalogueLeftRight() < 0) { + if (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) { + if (m_fMapSize > MENU_X(MAP_SIZE_TO_ALLOW_X_MOVE) && m_fMapSize - MENU_X(MAP_MIN_SIZE) + SCREEN_WIDTH/2 > m_fMapCenterX) + m_fMapCenterX += MENU_X(15.f); + m_bShowMouse = false; + } + } + + if (CPad::GetPad(0)->GetLeftMouseJustUp()) { + // The coordinates in aScreens->MENUPAGE_MAP. + if (m_nMousePosX > MENU_X_LEFT_ALIGNED(60.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(140.0f)) { + if (m_nMousePosY > MENU_Y(375.0f) && m_nMousePosY < MENU_Y(400.0f)) { + m_nHoverOption = HOVEROPTION_RANDOM_ITEM; + goBack = true; + } + } + } + + if (CPad::GetPad(0)->GetLeftMouse() && m_nMousePosX > m_nMouseOldPosX || CPad::GetPad(0)->GetRight() || + CPad::GetPad(0)->GetDPadRight() || CPad::GetPad(0)->GetAnalogueLeftRight() > 0) { + if (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) { + if (m_fMapSize > MENU_X(MAP_SIZE_TO_ALLOW_X_MOVE) && SCREEN_WIDTH/2 - (m_fMapSize - MENU_X(MAP_MIN_SIZE)) < m_fMapCenterX) + m_fMapCenterX -= MENU_X(15.f); + m_bShowMouse = false; + } + } + } + + + if (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) + lastMapTick = CTimer::GetTimeInMillisecondsPauseMode(); + +#ifndef MAP_ENHANCEMENTS + if (CPad::GetPad(0)->GetLeftMouseJustUp()) + CentreMousePointer(); +#endif + + if (CPad::GetPad(0)->GetLeftMouse()) { + if (m_nMousePosX < SCREEN_STRETCH_X(20.0f) || m_nMousePosX > SCREEN_STRETCH_X(620.0f) || m_nMousePosY < SCREEN_STRETCH_Y(20.0f) || m_nMousePosY > SCREEN_STRETCH_Y(428.0f)) { +#ifdef MAP_ENHANCEMENTS + justResetPointer = true; +#endif + CentreMousePointer(); + } + } + if (!CPad::GetPad(0)->GetLeftMouse() && !m_bShowMouse && (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY)) { + m_bShowMouse = true; + } + + static bool pressedL = false; + + if (!CPad::GetPad(0)->GetChar('L') && !CPad::GetPad(0)->GetChar('l')) { + pressedL = false; + } + + if (!pressedL) { + if (CPad::GetPad(0)->GetChar('L') || CPad::GetPad(0)->GetChar('l')) { + m_PrefsShowLegends = !m_PrefsShowLegends; + pressedL = true; + } + } + break; + } + case MENUPAGE_SOUND_SETTINGS: + if (CheckHover(MENU_X_LEFT_ALIGNED(177.f), MENU_X_LEFT_ALIGNED(238.f), MENU_Y(MENURADIO_SELECTOR_START_Y - 13.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT - 8.f))) { + m_nHoverOption = HOVEROPTION_PREV_RADIO; + } + + if (CheckHover(MENU_X_LEFT_ALIGNED(422.f), MENU_X_LEFT_ALIGNED(491.f), MENU_Y(MENURADIO_SELECTOR_START_Y - 13.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT - 8.f))) { + m_nHoverOption = HOVEROPTION_NEXT_RADIO; + } + break; + case MENUPAGE_STATS: + { + if (CPad::GetPad(0)->GetMouseWheelUpJustDown() || CPad::GetPad(0)->GetMouseWheelUpJustUp() || CPad::GetPad(0)->GetUp() || + CPad::GetPad(0)->GetDPadUp() || CPad::GetPad(0)->GetAnalogueUpDown() < 0) { + + m_StatsScrollSpeed = 20.0f; + m_StatsScrollDirection = 0; + + } else if (CPad::GetPad(0)->GetMouseWheelDownJustDown() || CPad::GetPad(0)->GetMouseWheelDownJustUp() || CPad::GetPad(0)->GetDown() || + CPad::GetPad(0)->GetDPadDown() || CPad::GetPad(0)->GetAnalogueUpDown() > 0) { + + m_StatsScrollSpeed = 20.0f; + m_StatsScrollDirection = 1; + + } else if (CPad::GetPad(0)->GetChar(' ')) { + m_StatsScrollSpeed = 0.0f; + } else + m_StatsScrollSpeed = 150.0f; + + static bool pressedS = false; + + if (!CPad::GetPad(0)->GetChar('S') && !CPad::GetPad(0)->GetChar('s')) { + pressedS = false; + } + + if (!pressedS) { + if (CPad::GetPad(0)->GetChar('S') || CPad::GetPad(0)->GetChar('s')) { + ExportStats(); + m_nHelperTextMsgId = 4; + m_nHelperTextAlpha = 300; + pressedS = true; + } + } + break; + } + } +} + +// Not original name +void +CMenuManager::ExportStats() +{ + char date[10]; + CFileMgr::SetDirMyDocuments(); + _strdate(date); + wchar *lastMission = TheText.Get(CStats::LastMissionPassedName[0] == '\0' ? "ITBEG" : CStats::LastMissionPassedName); + FILE *txtFile = fopen("stats.txt", "w"); + + if (txtFile) { + int statLines = CStats::ConstructStatLine(99999); + fprintf(txtFile, "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n"); + fprintf(txtFile, "\t\t\tGTA VICE CITY %s\n", UnicodeToAscii(TheText.Get("FEH_STA"))); + fprintf(txtFile, "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n\n"); + fprintf(txtFile, "%s: ", UnicodeToAscii(TheText.Get("FES_CMI"))); + fprintf(txtFile, "%s\n", UnicodeToAscii(lastMission)); + fprintf(txtFile, "%s: ", UnicodeToAscii(TheText.Get("FES_DAT"))); + fprintf(txtFile, "%s\n\n\n", date); + fprintf(txtFile, "%s ", UnicodeToAscii(TheText.Get("CRIMRA"))); + UnicodeStrcpy(gUString, CStats::FindCriminalRatingString()); + fprintf(txtFile, "%s (%d)\n\n\n", UnicodeToAscii(gUString), CStats::FindCriminalRatingNumber()); + for (int i = 0; i < statLines; ++i) { + CStats::ConstructStatLine(i); + char *statKey = UnicodeToAscii(gUString); + if (statKey[0] != '\0') + fprintf(txtFile, "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n%s\n", statKey); + + char *statValue = UnicodeToAscii(gUString2); + for (int j = 0; statValue[j] != '\0'; ++j) { + if (statValue[j] == '_') + statValue[j] = '\xBA'; // This is degree symbol, but my editors keeps messing up with it so I wrote hex representation + } + if (statValue) + fprintf(txtFile, "%s\n\n", statValue); + } + fprintf(txtFile, "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n"); + } + fclose(txtFile); + FILE *htmlFile = fopen("stats.html", "w"); + if (htmlFile) { + int statLines = CStats::ConstructStatLine(99999); + fprintf(htmlFile, "Grand Theft Auto Vice City Stats\n"); + fprintf(htmlFile, "\n"); + fprintf(htmlFile, "\n"); + fprintf(htmlFile, " \n"); + fprintf(htmlFile, "\n"); + fprintf(htmlFile, "\n"); + fprintf(htmlFile, " \n"); + fprintf(htmlFile, + "\n", UnicodeToAscii(lastMission)); + fprintf(htmlFile, " \n"); + fprintf(htmlFile, " \n"); + fprintf(htmlFile, "\n", statKey, rating); + + for (int k = 0; k < statLines; ++k) { + CStats::ConstructStatLine(k); + statKey = UnicodeToAscii(gUString); + if (statKey[0] != '\0') + fprintf(htmlFile, "\n"); + + fprintf(htmlFile, "\n"); + fprintf(htmlFile, "
-------------------------------------------------------------------------
\n"); + fprintf(htmlFile, "GRAND THEFT AUTO VICE CITY "); + fprintf(htmlFile, "%s
-------------------------------------------------------------------------
 

" + "%s: \n", UnicodeToAscii(TheText.Get("FES_DAT"))); + fprintf(htmlFile, "%s
%s:
", date, UnicodeToAscii(TheText.Get("FES_CMI"))); + fprintf(htmlFile, "%s

%s\n", UnicodeToAscii(TheText.Get("CRIMRA"))); + + UnicodeStrcpy(gUString, CStats::FindCriminalRatingString()); + char *statKey = UnicodeToAscii(gUString); + int rating = CStats::FindCriminalRatingNumber(); + fprintf(htmlFile, "%s (%d)
\n"); + + if (statKey[0] != '\0') + fprintf(htmlFile, "%s", statKey); + else + fprintf(htmlFile, " "); + + fprintf(htmlFile, "
\n"); + + char *statValue = UnicodeToAscii(gUString2); + for (int l = 0; statValue[l] != '\0'; ++l) { + if (statValue[l] == '_') + statValue[l] = '\xBA'; // This is degree symbol, but my editors keeps messing up with it so I wrote hex representation + } + if (statValue) + fprintf(htmlFile, "%s", statValue); + else + fprintf(htmlFile, " "); + } + fprintf(htmlFile, "

"); + fprintf(htmlFile, "\n"); + fprintf(htmlFile, "\n"); + fprintf(htmlFile, "\n"); + fprintf(htmlFile, "
rockstargames.com/vicecityrockstargames.com rockstarnorth.com
\n\n"); + } + fclose(htmlFile); + CFileMgr::SetDir(""); +} + +// Original name is unknown +void +CMenuManager::PrintRadioSelector(void) +{ + static PauseModeTime lastRadioChange = 0; + + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(418.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT), + MENU_X_LEFT_ALIGNED(228.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT), + MENU_X_LEFT_ALIGNED(428.f), MENU_Y(MENURADIO_SELECTOR_START_Y), + MENU_X_LEFT_ALIGNED(238.f), MENU_Y(MENURADIO_SELECTOR_START_Y), CRGBA(RADIO_SELECTOR_COLOR.r, RADIO_SELECTOR_COLOR.g, RADIO_SELECTOR_COLOR.b, FadeIn(180))); + + int rightMostSprite, rightMostStation; + if (DMAudio.IsMP3RadioChannelAvailable()) { + rightMostSprite = MENUSPRITE_MP3; + rightMostStation = USERTRACK; + } else { + rightMostSprite = MENUSPRITE_WAVE; + rightMostStation = WAVE; + } + #ifdef THIS_IS_STUPID + + // First radio + if (m_ScrollRadioBy == 1) { + if (m_PrefsRadioStation == 1) { + m_aFrontEndSprites[rightMostSprite].Draw(m_LeftMostRadioX, MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else if ( m_PrefsRadioStation == 0) { + m_aFrontEndSprites[rightMostSprite - 1].Draw(m_LeftMostRadioX, MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else { + m_aFrontEndSprites[m_PrefsRadioStation + MENUSPRITE_WILDSTYLE - 2].Draw(m_LeftMostRadioX, MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } + } + + // Second + if (m_PrefsRadioStation == 0) { + m_aFrontEndSprites[rightMostSprite].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else { + m_aFrontEndSprites[m_PrefsRadioStation + MENUSPRITE_WILDSTYLE - 1].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), + MENU_Y(MENURADIO_ICON_SIZE), CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } + + // Third (middle) + int prevStation = m_PrefsRadioStation - 1; + if (prevStation == rightMostStation) { + m_aFrontEndSprites[MENUSPRITE_WILDSTYLE + 1].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 3), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else if ( prevStation == rightMostStation - 1) { + m_aFrontEndSprites[MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 3), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else { + m_aFrontEndSprites[m_PrefsRadioStation + MENUSPRITE_WILDSTYLE + 1].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 3), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } + + // Fifth + if (m_ScrollRadioBy == -1) { + int prevStation = m_PrefsRadioStation - 1; + if (prevStation == rightMostStation) { + m_aFrontEndSprites[MENUSPRITE_WILDSTYLE + 4].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 4), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else if (prevStation == rightMostStation - 1) { + m_aFrontEndSprites[MENUSPRITE_WILDSTYLE + 1].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 4), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else if ( prevStation == rightMostStation - 2) { + m_aFrontEndSprites[MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 4), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else { + m_aFrontEndSprites[m_PrefsRadioStation + MENUSPRITE_WILDSTYLE + 2].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 4), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } + } + + // Fourth + if (m_ScrollRadioBy == 0) { + m_aFrontEndSprites[m_PrefsRadioStation + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 2 - 10.f), MENU_Y(MENURADIO_ICON_Y - 10.f), MENU_X(MENURADIO_ICON_SIZE) + MENU_X(20.f), MENU_Y(MENURADIO_ICON_SIZE) + MENU_Y(20.f), + CRGBA(255, 255, 255, FadeIn(255))); + } else { + if (m_PrefsRadioStation - 1 == rightMostStation) { + m_aFrontEndSprites[MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 2), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else { + m_aFrontEndSprites[m_PrefsRadioStation + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 2), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } + } +#else + int first = ((m_PrefsRadioStation - 2) + rightMostStation + 1) % (rightMostStation + 1); + int second = ((m_PrefsRadioStation - 1) + rightMostStation + 1) % (rightMostStation + 1); + int third = ((m_PrefsRadioStation) + rightMostStation + 1) % (rightMostStation + 1); + int fourth = ((m_PrefsRadioStation + 1) + rightMostStation + 1) % (rightMostStation + 1); + int fifth = ((m_PrefsRadioStation + 2) + rightMostStation + 1) % (rightMostStation + 1); + + // First one is only drawn on transition to next + if (m_ScrollRadioBy == 1) { + m_aFrontEndSprites[first + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX, MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } + + // Second + m_aFrontEndSprites[second + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + + // Fourth + m_aFrontEndSprites[fourth + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 3), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + + // Fifth one is only drawn on transition to prev. + if (m_ScrollRadioBy == -1) { + m_aFrontEndSprites[fifth + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 4), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } + + // Middle one(third) is colored differently depending on if it's in transition. + // If not in transition then this icon indicates selected radio, and should be on top of all icons. thus drawn last + if (m_ScrollRadioBy != 0) { + m_aFrontEndSprites[third + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 2), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else { + m_aFrontEndSprites[third + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 2 - 10.f), MENU_Y(MENURADIO_ICON_Y - 10.f), MENU_X(MENURADIO_ICON_SIZE) + MENU_X(20.f), MENU_Y(MENURADIO_ICON_SIZE) + MENU_Y(20.f), + CRGBA(255, 255, 255, FadeIn(255))); + } +#endif + + static bool radioChangeRequested = false; + static PauseModeTime lastScrollCheck = 0; + if (CTimer::GetTimeInMillisecondsPauseMode() - lastScrollCheck > 17) { + if (m_ScrollRadioBy == 1) { + if (m_LeftMostRadioX > MENU_X_LEFT_ALIGNED(MENURADIO_ICON_FIRST_X - MENURADIO_ICON_SIZE)) { + m_LeftMostRadioX -= MENU_X(6.f); + } else { + m_ScrollRadioBy = 0; + lastRadioChange = CTimer::GetTimeInMillisecondsPauseMode(); + radioChangeRequested = true; + } + } + if (m_ScrollRadioBy == -1) { + if (m_LeftMostRadioX < MENU_X_LEFT_ALIGNED(MENURADIO_ICON_FIRST_X - MENURADIO_ICON_SIZE)) { + m_LeftMostRadioX += MENU_X(6.f); + } else { + m_ScrollRadioBy = 0; + lastRadioChange = CTimer::GetTimeInMillisecondsPauseMode(); + radioChangeRequested = true; + } + } + lastScrollCheck = CTimer::GetTimeInMillisecondsPauseMode(); + } + // Background behind arrows + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(228.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT), + MENU_X_LEFT_ALIGNED(168.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT), + MENU_X_LEFT_ALIGNED(238.f), MENU_Y(MENURADIO_SELECTOR_START_Y), + MENU_X_LEFT_ALIGNED(178.f), MENU_Y(MENURADIO_SELECTOR_START_Y), + CRGBA(RADIO_SELECTOR_COLOR.r, RADIO_SELECTOR_COLOR.g, RADIO_SELECTOR_COLOR.b, FadeIn(255))); + + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(478.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT), + MENU_X_LEFT_ALIGNED(418.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT), + MENU_X_LEFT_ALIGNED(488.f), MENU_Y(MENURADIO_SELECTOR_START_Y), + MENU_X_LEFT_ALIGNED(428.f), MENU_Y(MENURADIO_SELECTOR_START_Y), + CRGBA(RADIO_SELECTOR_COLOR.r, RADIO_SELECTOR_COLOR.g, RADIO_SELECTOR_COLOR.b, FadeIn(255))); + + // Arrows and their shadows + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(216.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 48.f), MENU_X_LEFT_ALIGNED(196.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 36.f), MENU_X_LEFT_ALIGNED(216.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 22.f), MENU_X_LEFT_ALIGNED(196.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 36.f), CRGBA(0, 0, 0, FadeIn(255))); + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(213.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 45.f), MENU_X_LEFT_ALIGNED(193.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 33.f), MENU_X_LEFT_ALIGNED(213.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 19.f), MENU_X_LEFT_ALIGNED(193.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 33.f), CRGBA(97, 194, 247, FadeIn(255))); + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(440.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 48.f), MENU_X_LEFT_ALIGNED(460.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 36.f), MENU_X_LEFT_ALIGNED(440.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 22.f), MENU_X_LEFT_ALIGNED(460.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 36.f), CRGBA(0, 0, 0, FadeIn(255))); + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(443.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 45.f), MENU_X_LEFT_ALIGNED(463.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 33.f), MENU_X_LEFT_ALIGNED(443.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 19.f), MENU_X_LEFT_ALIGNED(463.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 33.f), CRGBA(97, 194, 247, FadeIn(255))); + if (radioChangeRequested) { + if (CTimer::GetTimeInMillisecondsPauseMode() - lastRadioChange > 50) { + DMAudio.SetRadioInCar(m_PrefsRadioStation); + DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); + OutputDebugString("FRONTEND RADIO STATION CHANGED"); + lastRadioChange = CTimer::GetTimeInMillisecondsPauseMode(); + radioChangeRequested = false; + } + } +} + +// Original name is unknown +void +CMenuManager::ProcessList(bool &optionSelected, bool &goBack) +{ + if (m_bWaitingForNewKeyBind) + return; + + if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { + m_nTotalListRow = m_nSkinsTotal; + } + if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { + // GetNumOptionsCntrlConfigScreens would have been a better choice + m_nTotalListRow = m_ControlMethod == CONTROL_CLASSIC ? 32 : 27; + if (m_nSelectedListRow > m_nTotalListRow) + m_nSelectedListRow = m_nTotalListRow - 1; + } + + if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { + m_bShowMouse = 0; + optionSelected = true; + } + if (CPad::GetPad(0)->GetBackspaceJustDown() && m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS && !field_159) { + if (m_nCurrExLayer == HOVEROPTION_LIST) { + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + m_bWaitingForNewKeyBind = true; + m_bStartWaitingForKeyBind = true; + m_bKeyChangeNotProcessed = true; + pControlEdit = &m_KeyPressedCode; + } + } else { + field_159 = false; + } + + static PauseModeTime lastTimeClickedScrollButton = 0; + + if (CTimer::GetTimeInMillisecondsPauseMode() - lastTimeClickedScrollButton >= 200) { + m_bPressedPgUpOnList = false; + m_bPressedPgDnOnList = false; + m_bPressedUpOnList = false; + m_bPressedDownOnList = false; + m_bPressedScrollButton = false; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + } + + if (CPad::GetPad(0)->GetTabJustDown()) { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + m_bShowMouse = false; + switch (m_nCurrExLayer) { + case HOVEROPTION_BACK: + default: + m_nCurrExLayer = HOVEROPTION_LIST; + break; + case HOVEROPTION_LIST: + m_nCurrExLayer = HOVEROPTION_USESKIN; + break; + case HOVEROPTION_USESKIN: + m_nCurrExLayer = HOVEROPTION_BACK; + } + if (((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) && strcmp(m_aSkinName, m_PrefsSkinFile) == 0) { + m_nCurrExLayer = HOVEROPTION_BACK; + } + if ((m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) { + m_nCurrExLayer = HOVEROPTION_BACK; + } + } + + bool pressed = false; + if (CPad::GetPad(0)->GetUp() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) { + m_bShowMouse = false; + pressed = true; + } else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) { + m_bShowMouse = true; + pressed = true; + } + + // Up + if (pressed) { + m_nCurrExLayer = HOVEROPTION_LIST; + if (!m_bPressedUpOnList) { + m_bPressedUpOnList = true; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + ScrollUpListByOne(); + } + } else { + m_bPressedUpOnList = false; + } + + pressed = false; + if (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) { + m_bShowMouse = false; + pressed = true; + } else if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) { + m_bShowMouse = true; + pressed = true; + } + + // Down + if (pressed) { + m_nCurrExLayer = HOVEROPTION_LIST; + if (!m_bPressedDownOnList) { + m_bPressedDownOnList = true; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + ScrollDownListByOne(); + } + } else { + m_bPressedDownOnList = false; + } + + if (m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { + if (!CPad::GetPad(0)->GetPageUp()) { + m_bPressedPgUpOnList = false; + } else { + m_nCurrExLayer = HOVEROPTION_LIST; + if (!m_bPressedPgUpOnList) { + m_bPressedPgUpOnList = true; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + m_bShowMouse = false; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + PageUpList(false); + } + } + if (!CPad::GetPad(0)->GetPageDown()) { + m_bPressedPgDnOnList = false; + } else { + m_nCurrExLayer = HOVEROPTION_LIST; + if (!m_bPressedPgDnOnList) { + m_bPressedPgDnOnList = true; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + m_bShowMouse = false; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + PageDownList(false); + } + } + if (CPad::GetPad(0)->GetHome()) { + m_nCurrExLayer = HOVEROPTION_LIST; + m_bShowMouse = false; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + if (m_nTotalListRow >= MAX_VISIBLE_OPTION_ON_SCREEN) { + m_nFirstVisibleRowOnList = 0; + } + m_nSelectedListRow = 0; + m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; + } + if (CPad::GetPad(0)->GetEnd()) { + m_nCurrExLayer = HOVEROPTION_LIST; + m_bShowMouse = false; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + if (m_nTotalListRow >= MAX_VISIBLE_OPTION_ON_SCREEN) { + m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN; + } + m_nSelectedListRow = m_nTotalListRow - 1; + m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; + } + } + + if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetBackJustDown()) { + m_bShowMouse = false; + goBack = true; + } + + if (CPad::GetPad(0)->GetLeftMouseJustDown()) { + switch (m_nHoverOption) { + case HOVEROPTION_BACK: + goBack = true; + break; + case HOVEROPTION_PAGEUP: + PageUpList(true); + break; + case HOVEROPTION_PAGEDOWN: + PageDownList(true); + break; + case HOVEROPTION_USESKIN: + if (m_nSkinsTotal > 0) { + m_pSelectedSkin = m_pSkinListHead.nextSkin; + strcpy(m_PrefsSkinFile, m_aSkinName); + CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); + SaveSettings(); + } + } + } + + if (CPad::GetPad(0)->GetLeftMouseJustDown()) { + switch (m_nHoverOption) { + case HOVEROPTION_OVER_SCROLL_UP: + m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_UP; + break; + case HOVEROPTION_OVER_SCROLL_DOWN: + m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_DOWN; + break; + case HOVEROPTION_LIST: + m_nHoverOption = HOVEROPTION_SKIN; + } + } else if ((CPad::GetPad(0)->GetLeftMouseJustUp()) + && ((m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP || (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN)))) { + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + } + + if (!CPad::GetPad(0)->GetLeftMouse()) { + holdingScrollBar = false; + } else { + if ((m_nHoverOption == HOVEROPTION_HOLDING_SCROLLBAR) || holdingScrollBar) { + holdingScrollBar = true; + // TODO: This part is a bit hard to reverse. Not much code tho + assert(0 && "Holding scrollbar isn't done yet"); + } else { + switch (m_nHoverOption) { + case HOVEROPTION_OVER_SCROLL_UP: + case HOVEROPTION_CLICKED_SCROLL_UP: + if (!m_bPressedScrollButton) { + m_bPressedScrollButton = true; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + ScrollUpListByOne(); + } + break; + case HOVEROPTION_OVER_SCROLL_DOWN: + case HOVEROPTION_CLICKED_SCROLL_DOWN: + if (!m_bPressedScrollButton) { + m_bPressedScrollButton = true; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + ScrollDownListByOne(); + } + break; + default: + m_bPressedScrollButton = false; + } + } + } +} + +void +CMenuManager::UserInput(void) +{ + bool goBack = false; + bool optionSelected = false; + bool goUp = false; + bool goDown = false; + int8 changeValueBy; + + if (!m_AllowNavigation && m_firstStartCounter == 255) + m_AllowNavigation = true; + if (!m_bShowMouse && m_nCurrScreen != MENUPAGE_MAP && (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY)) { + m_bShowMouse = true; + } + + static int oldOption = -99; + oldOption = m_nCurrOption; +#ifdef SCROLLABLE_PAGES + int firstOption = SCREEN_HAS_AUTO_SCROLLBAR ? m_nFirstVisibleRowOnList : 0; + int scrollOffset = aScreens[m_nCurrScreen].m_aEntries[firstOption].m_Y - aScreens[m_nCurrScreen].m_aEntries[0].m_Y; + for (int rowToCheck = firstOption; rowToCheck < firstOption + MAX_VISIBLE_OPTION && rowToCheck < NUM_MENUROWS; ++rowToCheck) { +#else + for (int rowToCheck = 0; rowToCheck < NUM_MENUROWS; ++rowToCheck) { +#endif + if (aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_NOTHING || + aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_LABEL) + continue; + + // unused: CFont::GetStringWidth(TheText.Get(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_EntryName), true); + // So they also wanted the compare X, but they abandoned the idea later on + + if (m_nMousePosY > MENU_Y(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Y MINUS_SCROLL_OFFSET) && + m_nMousePosY < MENU_Y(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Y MINUS_SCROLL_OFFSET PLUS_LINE_HEIGHT_ON_SCREEN)) { + static int oldScreen = m_nCurrScreen; + + m_nOptionMouseHovering = rowToCheck; + if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { + m_nCurrOption = rowToCheck; + m_bShowMouse = true; + } + + int action = aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action; + if (action != MENUACTION_BRIGHTNESS && action != MENUACTION_DRAWDIST && action != MENUACTION_MUSICVOLUME + && action != MENUACTION_SFXVOLUME && action != MENUACTION_MOUSESENS && action != MENUACTION_MP3VOLUMEBOOST) + m_nHoverOption = HOVEROPTION_RANDOM_ITEM; + + break; + } + if (m_bShowMouse && m_nMenuFadeAlpha == 255) { + m_nOptionMouseHovering = oldOption; + m_nCurrOption = oldOption; + } + } + + if (m_bShowMouse) { + if (oldOption != m_nCurrOption) { + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_LABEL) { + ++m_nCurrOption; + ++m_nOptionMouseHovering; + } + m_nOptionHighlightTransitionBlend = 0; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + } + } + + m_nMouseOldPosX = m_nMousePosX; + m_nMouseOldPosY = m_nMousePosY; + m_nMousePosX = m_nMouseTempPosX; + m_nMousePosY = m_nMouseTempPosY; + + if (m_nMousePosX < 0) m_nMousePosX = 0; + if (m_nMousePosX > SCREEN_WIDTH) m_nMousePosX = SCREEN_WIDTH; + if (m_nMousePosY < 0) m_nMousePosY = 0; + if (m_nMousePosY > SCREEN_HEIGHT) m_nMousePosY = SCREEN_HEIGHT; + + changeValueBy = 0; + if (hasNativeList(m_nCurrScreen)) { + ProcessList(optionSelected, goBack); + } else { + AdditionalOptionInput(goBack); + + if (m_AllowNavigation && + (CPad::GetPad(0)->GetDownJustDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown())) { + m_bShowMouse = false; + goDown = true; + m_nOptionHighlightTransitionBlend = 0; + + } else if (m_AllowNavigation && + (CPad::GetPad(0)->GetUpJustDown() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown())) { + m_bShowMouse = false; + goUp = true; + m_nOptionHighlightTransitionBlend = 0; + } + + if ((m_nCurrOption == 0) && (m_nCurrScreen == MENUPAGE_PAUSE_MENU)) { + if (CPad::GetPad(0)->GetEnterJustUp() || CPad::GetPad(0)->GetCrossJustUp()) { + m_bShowMouse = false; + optionSelected = true; + } + } else { + if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { + m_bShowMouse = false; + optionSelected = true; + } + } + + if (CPad::GetPad(0)->GetLeftMouseJustUp() && m_nCurrScreen != MENUPAGE_MAP) { + if (m_nHoverOption == HOVEROPTION_RANDOM_ITEM) + optionSelected = true; + else if (m_nHoverOption == HOVEROPTION_NEXT_RADIO) + ChangeRadioStation(1); + else if (m_nHoverOption == HOVEROPTION_PREV_RADIO) + ChangeRadioStation(-1); + } + + if (CPad::GetPad(0)->GetLeftMouse()) { + switch (m_nHoverOption) { + case HOVEROPTION_INCREASE_BRIGHTNESS: + case HOVEROPTION_INCREASE_MP3BOOST: + case HOVEROPTION_INCREASE_DRAWDIST: + case HOVEROPTION_INCREASE_MUSICVOLUME: + case HOVEROPTION_INCREASE_SFXVOLUME: + case HOVEROPTION_INCREASE_MOUSESENS: + CheckSliderMovement(1); + break; + case HOVEROPTION_DECREASE_BRIGHTNESS: + case HOVEROPTION_DECREASE_MP3BOOST: + case HOVEROPTION_DECREASE_DRAWDIST: + case HOVEROPTION_DECREASE_MUSICVOLUME: + case HOVEROPTION_DECREASE_SFXVOLUME: + case HOVEROPTION_DECREASE_MOUSESENS: + CheckSliderMovement(-1); + break; + } + } + +#ifdef SCROLLABLE_PAGES + if (m_nTotalListRow > MAX_VISIBLE_OPTION) { + bool temp = false; + + m_nSelectedListRow = m_nCurrOption; + + // ignore detected back/select states, it's our screen's job + ProcessList(temp, temp); + + // and ignore our screen's goUp/Down, now it's ProcessList's job + goUp = false; + goDown = false; + m_nCurrOption = m_nSelectedListRow; + + if (oldOption != m_nCurrOption) + m_nOptionHighlightTransitionBlend = 0; + } + + // Prevent sound on scroll. Mouse wheel is now belongs to us! + if (!(m_nTotalListRow > MAX_VISIBLE_OPTION && (CPad::GetPad(0)->GetMouseWheelUpJustDown() || CPad::GetPad(0)->GetMouseWheelDownJustDown()))) +#endif + if (CPad::GetPad(0)->GetLeftMouseJustUp() || CPad::GetPad(0)->GetLeftJustUp() || CPad::GetPad(0)->GetRightJustUp() + || CPad::GetPad(0)->GetDPadLeftJustUp() || CPad::GetPad(0)->GetDPadRightJustUp() + || CPad::GetPad(0)->GetAnaloguePadLeftJustUp() || CPad::GetPad(0)->GetAnaloguePadRightJustUp() + || CPad::GetPad(0)->GetMouseWheelUpJustDown() || CPad::GetPad(0)->GetMouseWheelDownJustDown()) { + int option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; + if (option == MENUACTION_BRIGHTNESS) + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0); + else if (option == MENUACTION_SFXVOLUME) + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_AUDIO_TEST, 0); + else if (option == MENUACTION_DRAWDIST || option == MENUACTION_MOUSESENS) + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0); + + } + if (CPad::GetPad(0)->GetBackJustDown() || CPad::GetPad(0)->GetEscapeJustDown()) { + if (m_nCurrScreen != MENUPAGE_START_MENU && m_nCurrScreen != MENUPAGE_PAUSE_MENU && m_nCurrScreen != MENUPAGE_CHOOSE_SAVE_SLOT + && m_nCurrScreen != MENUPAGE_SAVE_CHEAT_WARNING && m_nCurrScreen != MENUPAGE_SAVING_IN_PROGRESS + && m_nCurrScreen != MENUPAGE_DELETING_IN_PROGRESS && m_nCurrScreen != MENUPAGE_OUTRO) + { + m_bShowMouse = false; + goBack = true; + } + } + + if (((goDown) || (goUp)) || (optionSelected)) { + goBack = false; + } + + } + + int curAction = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; + if (CPad::GetPad(0)->GetLeft() || CPad::GetPad(0)->GetPedWalkLeftRight() < 0 || CPad::GetPad(0)->GetDPadLeft()) { + static PauseModeTime lastSliderDecrease = 0; + if (CTimer::GetTimeInMillisecondsPauseMode() - lastSliderDecrease > 150) { + if (curAction == MENUACTION_BRIGHTNESS || curAction == MENUACTION_MUSICVOLUME || + curAction == MENUACTION_SFXVOLUME || curAction == MENUACTION_RADIO || + curAction == MENUACTION_DRAWDIST || curAction == MENUACTION_MOUSESENS || + curAction == MENUACTION_MP3VOLUMEBOOST) + changeValueBy = -1; + + lastSliderDecrease = CTimer::GetTimeInMillisecondsPauseMode(); + } + } else if (CPad::GetPad(0)->GetRight() || CPad::GetPad(0)->GetPedWalkLeftRight() > 0 || CPad::GetPad(0)->GetDPadRight()) { + static PauseModeTime lastSliderIncrease = 0; + if (CTimer::GetTimeInMillisecondsPauseMode() - lastSliderIncrease > 150) { + if (curAction == MENUACTION_BRIGHTNESS || curAction == MENUACTION_MUSICVOLUME || + curAction == MENUACTION_SFXVOLUME || curAction == MENUACTION_RADIO || + curAction == MENUACTION_DRAWDIST || curAction == MENUACTION_MOUSESENS || + curAction == MENUACTION_MP3VOLUMEBOOST) + changeValueBy = 1; + lastSliderIncrease = CTimer::GetTimeInMillisecondsPauseMode(); + } + } + +#ifdef SCROLLABLE_PAGES + if (!SCREEN_HAS_AUTO_SCROLLBAR) +#endif + { + if (CPad::GetPad(0)->GetMouseWheelUpJustDown()) { + changeValueBy = 1; + } else if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) { + changeValueBy = -1; + } + } + + if (m_AllowNavigation) { + if (CPad::GetPad(0)->GetRightJustDown() || CPad::GetPad(0)->GetAnaloguePadRight() || CPad::GetPad(0)->GetDPadRightJustDown()) { + m_bShowMouse = false; + changeValueBy = 1; + } + } + + if (m_AllowNavigation) { + if (CPad::GetPad(0)->GetLeftJustDown() || CPad::GetPad(0)->GetAnaloguePadLeft() || CPad::GetPad(0)->GetDPadLeftJustDown()) { + m_bShowMouse = false; + changeValueBy = -1; + } + } + if (changeValueBy != 0) { + if ((m_nCurrScreen == MENUPAGE_SOUND_SETTINGS || m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS || m_nCurrScreen == MENUPAGE_CONTROLLER_PC || m_nCurrScreen == MENUPAGE_MOUSE_CONTROLS) + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_NOTHING + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_LABEL + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_YES + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_NO + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_CHANGEMENU + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_KEYBOARDCTRLS + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_GOBACK + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_RESTOREDEF + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_DRAWDIST + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_MOUSESENS + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_MP3VOLUMEBOOST) { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0); + } + } + ProcessUserInput(goDown, goUp, optionSelected, goBack, changeValueBy); +#ifdef CUSTOM_FRONTEND_OPTIONS + if (aScreens[m_nCurrScreen].m_aEntries[oldOption].m_Action < MENUACTION_NOTHING) { // CFO check + CMenuScreenCustom::CMenuEntry &oldEntry = aScreens[m_nCurrScreen].m_aEntries[oldOption]; + if (m_nCurrOption != oldOption) { + if (oldEntry.m_Action == MENUACTION_CFO_DYNAMIC) + if(oldEntry.m_CFODynamic->buttonPressFunc) + oldEntry.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); + + if (oldEntry.m_Action == MENUACTION_CFO_SELECT && oldEntry.m_CFOSelect->onlyApplyOnEnter) { + if (oldEntry.m_CFOSelect->displayedValue != oldEntry.m_CFOSelect->lastSavedValue) + SetHelperText(3); // Restored original value + + oldEntry.m_CFOSelect->displayedValue = oldEntry.m_CFOSelect->lastSavedValue = *oldEntry.m_CFO->value; + } + } else if (oldEntry.m_Action == MENUACTION_CFO_SELECT && oldEntry.m_CFOSelect->onlyApplyOnEnter) { + if (oldEntry.m_CFOSelect->displayedValue != *oldEntry.m_CFO->value) + SetHelperText(1); // Enter to apply + else if (m_nHelperTextMsgId == 1) + ResetHelperText(); // Applied + } + } +#endif +} + +void +CMenuManager::ProcessUserInput(uint8 goDown, uint8 goUp, uint8 optionSelected, uint8 goBack, int8 changeAmount) +{ + if (m_nCurrScreen == MENUPAGE_OUTRO) + return; + + if (m_bWaitingForNewKeyBind) { + if (m_bStartWaitingForKeyBind) + m_bStartWaitingForKeyBind = false; + else { + pControlEdit = CPad::EditCodesForControls(pControlEdit, 1); + JoyButtonJustClicked = false; + MouseButtonJustClicked = false; + + if (CPad::GetPad(0)->GetLeftMouseJustDown()) + MouseButtonJustClicked = rsMOUSELEFTBUTTON; + else if (CPad::GetPad(0)->GetRightMouseJustUp()) + MouseButtonJustClicked = rsMOUSERIGHTBUTTON; + else if (CPad::GetPad(0)->GetMiddleMouseJustUp()) + MouseButtonJustClicked = rsMOUSMIDDLEBUTTON; + else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) + MouseButtonJustClicked = rsMOUSEWHEELUPBUTTON; + else if (CPad::GetPad(0)->GetMouseWheelDownJustUp()) + MouseButtonJustClicked = rsMOUSEWHEELDOWNBUTTON; + else if (CPad::GetPad(0)->GetMouseX1JustUp()) + MouseButtonJustClicked = rsMOUSEX1BUTTON; + else if (CPad::GetPad(0)->GetMouseX2JustUp()) + MouseButtonJustClicked = rsMOUSEX2BUTTON; + + JoyButtonJustClicked = ControlsManager.GetJoyButtonJustDown(); + + int32 TypeOfControl = KEYBOARD; + if (JoyButtonJustClicked) + TypeOfControl = JOYSTICK; + if (MouseButtonJustClicked) + TypeOfControl = MOUSE; + if (*pControlEdit != rsNULL) + TypeOfControl = KEYBOARD; + + if (!m_bKeyIsOK) { + pControlEdit = nil; + m_bWaitingForNewKeyBind = false; + m_KeyPressedCode = -1; + m_bStartWaitingForKeyBind = false; + } else if (!m_bKeyChangeNotProcessed) { + if (*pControlEdit != rsNULL || MouseButtonJustClicked || JoyButtonJustClicked) + CheckCodesForControls(TypeOfControl); + + field_159 = true; + } else { + for (int i = 0; i < 4; i++) + ControlsManager.ClearSettingsAssociatedWithAction((e_ControllerAction)m_CurrCntrlAction, (eControllerType)i); + m_bKeyIsOK = false; + m_bKeyChangeNotProcessed = false; + } + } + } + + if (pEditString || pControlEdit) + return; + +#ifdef USE_DEBUG_SCRIPT_LOADER + if (m_nCurrScreen == MENUPAGE_START_MENU || m_nCurrScreen == MENUPAGE_NEW_GAME || m_nCurrScreen == MENUPAGE_NEW_GAME_RELOAD) { +#ifdef RW_GL3 + if (glfwGetKey(PSGLOBAL(window), GLFW_KEY_R) == GLFW_PRESS) { + scriptToLoad = 1; + DoSettingsBeforeStartingAGame(); + return; + } +#elif defined _WIN32 + if (GetAsyncKeyState('R') & 0x8000) { + scriptToLoad = 1; + DoSettingsBeforeStartingAGame(); + return; + } +#endif + } +#endif + + int oldOption = m_nCurrOption; + if (goDown) { + if (m_nCurrScreen != MENUPAGE_MAP) + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + + m_nCurrOption++; + if (m_nCurrOption == NUM_MENUROWS || (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_NOTHING)) { + m_nCurrOption = 0; + } + if (oldOption != m_nCurrOption) + m_nOptionHighlightTransitionBlend = 0; + } + if (goUp) { + if (m_nCurrScreen != MENUPAGE_MAP) + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + + if (m_nCurrOption == (aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL)) { + while (m_nCurrOption != NUM_MENUROWS - 1 + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption + 1].m_Action != MENUACTION_NOTHING) { + m_nCurrOption++; + } + } else { + m_nCurrOption--; + } + if (oldOption != m_nCurrOption) + m_nOptionHighlightTransitionBlend = 0; + } + + if (optionSelected && m_nMenuFadeAlpha == 255) { + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu == MENUPAGE_NEW_GAME_RELOAD && m_bGameNotLoaded) { + DoSettingsBeforeStartingAGame(); + } else if (hasNativeList(m_nCurrScreen)) { + switch (m_nCurrExLayer) { + case HOVEROPTION_LIST: + if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { + m_bWaitingForNewKeyBind = true; + m_bStartWaitingForKeyBind = true; + pControlEdit = &m_KeyPressedCode; + } + if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { + strcpy(m_PrefsSkinFile, m_aSkinName); + CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); + m_nCurrExLayer = HOVEROPTION_BACK; + SaveSettings(); + } + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + break; + case HOVEROPTION_USESKIN: + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + strcpy(m_PrefsSkinFile, m_aSkinName); + CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); + m_nCurrExLayer = HOVEROPTION_BACK; + SaveSettings(); + break; + case HOVEROPTION_BACK: + default: + goBack = true; + break; + } + if (m_nSkinsTotal > 0) { + m_pSelectedSkin = m_pSkinListHead.nextSkin; + strcpy(m_PrefsSkinFile, m_aSkinName); + CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); + SaveSettings(); + } + } + + int option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; +#ifdef FIX_BUGS + int currScreen = m_nCurrScreen; + int currOption = m_nCurrOption; +#endif + switch (option) { + case MENUACTION_CHANGEMENU: + case MENUACTION_YES: + case MENUACTION_NO: + SwitchToNewScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu); + break; + case MENUACTION_RADIO: + ChangeRadioStation(1); + break; + case MENUACTION_LANG_ENG: + m_PrefsLanguage = LANGUAGE_AMERICAN; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_FRE: + m_PrefsLanguage = LANGUAGE_FRENCH; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_GER: + m_PrefsLanguage = LANGUAGE_GERMAN; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_ITA: + m_PrefsLanguage = LANGUAGE_ITALIAN; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_SPA: + m_PrefsLanguage = LANGUAGE_SPANISH; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_CHECKSAVE: + { + int saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot; + + if (saveSlot >= SAVESLOT_1 && saveSlot <= SAVESLOT_8) { + m_nCurrSaveSlot = saveSlot - SAVESLOT_1; + if (Slots[m_nCurrSaveSlot] != SLOT_EMPTY && Slots[m_nCurrSaveSlot] != SLOT_CORRUPTED) { + if (m_nCurrScreen == MENUPAGE_CHOOSE_LOAD_SLOT) { + SwitchToNewScreen(MENUPAGE_LOAD_SLOT_CONFIRM); + } else if (m_nCurrScreen == MENUPAGE_CHOOSE_DELETE_SLOT) { + SwitchToNewScreen(MENUPAGE_DELETE_SLOT_CONFIRM); + } + } + } + break; + } + case MENUACTION_NEWGAME: + DoSettingsBeforeStartingAGame(); + break; +#ifdef LEGACY_MENU_OPTIONS + case MENUACTION_RELOADIDE: + CFileLoader::ReloadObjectTypes("GTA3.IDE"); + break; +#endif + case MENUACTION_RESUME_FROM_SAVEZONE: + RequestFrontEndShutDown(); + break; + case MENUACTION_LOADRADIO: + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { + SwitchToNewScreen(MENUPAGE_SOUND_SETTINGS); + DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); + OutputDebugString("STARTED PLAYING FRONTEND AUDIO TRACK"); + } + break; + case MENUACTION_SAVEGAME: + { + int saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot; + + if (saveSlot >= 2 && saveSlot <= 9) { + m_nCurrSaveSlot = m_nCurrOption; + SwitchToNewScreen(MENUPAGE_SAVE_OVERWRITE_CONFIRM); + } + break; + } + case MENUACTION_RADARMODE: + if (++m_PrefsRadarMode > 2) + m_PrefsRadarMode = 0; + SaveSettings(); + break; + case MENUACTION_GOBACK: + goBack = true; + break; + case MENUACTION_KEYBOARDCTRLS: + SwitchToNewScreen(MENUPAGE_KEYBOARD_CONTROLS); + m_nSelectedListRow = 0; + m_nCurrExLayer = HOVEROPTION_LIST; + break; + case MENUACTION_GETKEY: + m_CurrCntrlAction = GetStartOptionsCntrlConfigScreens() + m_nCurrOption; + m_bKeyIsOK = true; + m_bWaitingForNewKeyBind = true; + m_bStartWaitingForKeyBind = true; + pControlEdit = &m_KeyPressedCode; + break; + case MENUACTION_CANCELGAME: + DMAudio.Service(); + SwitchToNewScreen(MENUPAGE_OUTRO); + break; + case MENUACTION_RESUME: +#ifdef LEGACY_MENU_OPTIONS + if (m_PrefsVsyncDisp != m_PrefsVsync) { + m_PrefsVsync = m_PrefsVsyncDisp; + } +#endif + RequestFrontEndShutDown(); + break; + case MENUACTION_DONTCANCEL: + SwitchToNewScreen(-2); + break; + case MENUACTION_SCREENRES: + if (m_nDisplayVideoMode != m_nPrefsVideoMode) { + m_nPrefsVideoMode = m_nDisplayVideoMode; + _psSelectScreenVM(m_nPrefsVideoMode); + DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND); + DMAudio.Service(); + CentreMousePointer(); + m_bShowMouse = true; + m_nCurrOption = 5; // TODO(Miami): Because selected option is resetted after res. change. We'll need to revisit that. + m_nOptionHighlightTransitionBlend = 0; + SaveSettings(); + } + break; + case MENUACTION_AUDIOHW: + { + int selectedProvider = m_nPrefsAudio3DProviderIndex; + if (selectedProvider != NO_AUDIO_PROVIDER) { + if (selectedProvider == -1) + selectedProvider = m_nPrefsAudio3DProviderIndex = DMAudio.AutoDetect3DProviders(); + + m_nPrefsAudio3DProviderIndex = DMAudio.SetCurrent3DProvider(m_nPrefsAudio3DProviderIndex); + if (selectedProvider != m_nPrefsAudio3DProviderIndex) { + SetHelperText(5); + } + SaveSettings(); + } + break; + } + case MENUACTION_SPEAKERCONF: + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { + if (--m_PrefsSpeakers < 0) + m_PrefsSpeakers = 2; + DMAudio.SetSpeakerConfig(m_PrefsSpeakers); + SaveSettings(); + } + break; + case MENUACTION_PLAYERSETUP: + CPlayerSkin::BeginFrontendSkinEdit(); + SwitchToNewScreen(MENUPAGE_SKIN_SELECT); + m_bSkinsEnumerated = false; + m_nCurrExLayer = HOVEROPTION_LIST; + break; + case MENUACTION_RESTOREDEF: + if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { + m_nPrefsAudio3DProviderIndex = DMAudio.AutoDetect3DProviders(); + DMAudio.SetCurrent3DProvider(m_nPrefsAudio3DProviderIndex); + m_PrefsSfxVolume = 49; + m_PrefsMusicVolume = 49; + m_PrefsRadioStation = EMOTION; + m_PrefsMP3BoostVolume = 0; + m_PrefsStereoMono = 1; + m_PrefsSpeakers = 0; + DMAudio.SetMP3BoostVolume(m_PrefsMP3BoostVolume); + DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); + DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); + DMAudio.SetRadioInCar(m_PrefsRadioStation); + DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); + SaveSettings(); + } else if (m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS) { + m_PrefsBrightness = 256; + m_PrefsLOD = 1.2f; +#ifdef LEGACY_MENU_OPTIONS + m_PrefsVsync = true; +#endif + CRenderer::ms_lodDistScale = m_PrefsLOD; + m_PrefsShowSubtitles = false; +#ifdef ASPECT_RATIO_SCALE + m_PrefsUseWideScreen = AR_AUTO; +#else + m_PrefsUseWideScreen = false; +#endif + m_PrefsShowLegends = true; + m_PrefsVsyncDisp = true; + m_PrefsFrameLimiter = true; + m_PrefsRadarMode = 0; + m_PrefsShowHud = true; + m_nDisplayVideoMode = m_nPrefsVideoMode; + CMBlur::BlurOn = false; +#ifdef CUSTOM_FRONTEND_OPTIONS + extern void RestoreDefGraphics(int8); + extern void RestoreDefDisplay(int8); + + RestoreDefGraphics(FEOPTION_ACTION_SELECT); + RestoreDefDisplay(FEOPTION_ACTION_SELECT); +#endif + SaveSettings(); + } else if (m_nCurrScreen == MENUPAGE_CONTROLLER_PC) { + ControlsManager.MakeControllerActionsBlank(); + ControlsManager.InitDefaultControlConfiguration(); + ControlsManager.InitDefaultControlConfigMouse(MousePointerStateHelper.GetMouseSetUp()); +#if !defined RW_GL3 + if (AllValidWinJoys.m_aJoys[JOYSTICK1].m_bInitialised) { + DIDEVCAPS devCaps; + devCaps.dwSize = sizeof(DIDEVCAPS); + PSGLOBAL(joy1)->GetCapabilities(&devCaps); + ControlsManager.InitDefaultControlConfigJoyPad(devCaps.dwButtons); + } +#else + if (PSGLOBAL(joy1id) != -1 && glfwJoystickPresent(PSGLOBAL(joy1id))) { + int count; + glfwGetJoystickButtons(PSGLOBAL(joy1id), &count); + ControlsManager.InitDefaultControlConfigJoyPad(count); + } +#endif + MousePointerStateHelper.bInvertVertically = true; + TheCamera.m_bHeadBob = false; +#ifdef FIX_BUGS + TheCamera.m_fMouseAccelVertical = 0.003f; +#endif + TheCamera.m_fMouseAccelHorzntl = 0.0025f; + CVehicle::m_bDisableMouseSteering = true; + m_ControlMethod = CONTROL_STANDARD; +#ifdef PC_PLAYER_CONTROLS + TheCamera.m_bUseMouse3rdPerson = true; +#else + TheCamera.m_bUseMouse3rdPerson = false; +#endif + SaveSettings(); +#ifdef LOAD_INI_SETTINGS + SaveINIControllerSettings(); +#endif + } + SetHelperText(2); + break; + case MENUACTION_CTRLMETHOD: + if (m_ControlMethod == CONTROL_CLASSIC) { + CCamera::m_bUseMouse3rdPerson = true; + m_ControlMethod = CONTROL_STANDARD; + } else { + CCamera::m_bUseMouse3rdPerson = false; + m_ControlMethod = CONTROL_CLASSIC; + } + SaveSettings(); + break; +#ifdef CUSTOM_FRONTEND_OPTIONS + case MENUACTION_CFO_SELECT: + case MENUACTION_CFO_DYNAMIC: + CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption]; + if (option.m_Action == MENUACTION_CFO_SELECT) { + if (option.m_CFOSelect->disableIfGameLoaded && !m_bGameNotLoaded) + break; + + if (!option.m_CFOSelect->onlyApplyOnEnter) { + option.m_CFOSelect->displayedValue++; + if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts || option.m_CFOSelect->displayedValue < 0) + option.m_CFOSelect->displayedValue = 0; + } + int8 oldValue = *option.m_CFO->value; + + *option.m_CFO->value = option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue; + + // Now everything is saved in .ini, and LOAD_INI_SETTINGS is fundamental for CFO + // if (option.m_CFOSelect->save) + SaveSettings(); + + if (option.m_CFOSelect->displayedValue != oldValue && option.m_CFOSelect->changeFunc) + option.m_CFOSelect->changeFunc(oldValue, option.m_CFOSelect->displayedValue); + + } else if (option.m_Action == MENUACTION_CFO_DYNAMIC) { + if (option.m_CFODynamic->buttonPressFunc) + option.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_SELECT); + } + + break; +#endif + } + ProcessOnOffMenuOptions(); + if (!goBack) { +#ifdef FIX_BUGS + int saveSlot = aScreens[currScreen].m_aEntries[currOption].m_SaveSlot; + if (saveSlot >= SAVESLOT_1 && saveSlot <= SAVESLOT_8 && Slots[currOption] != SLOT_OK) +#else + int saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot; + if (saveSlot >= SAVESLOT_1 && saveSlot <= SAVESLOT_8 && Slots[m_nCurrOption] != SLOT_OK) +#endif + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); + else + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0); + } + } + + if (goBack) { + if (m_NoEmptyBinding) { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_BACK, 0); + SwitchToNewScreen(-2); + if (hasNativeList(m_nCurrScreen)) { + m_nTotalListRow = 0; + } + } else { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); + m_ShowEmptyBindingError = true; + } + } + + if (changeAmount != 0) { + switch (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action) { +#ifdef GAMEPAD_MENU + case MENUACTION_CTRLCONFIG: + CPad::GetPad(0)->Mode += changeAmount; + if (CPad::GetPad(0)->Mode > 3) + CPad::GetPad(0)->Mode = 0; + else if (CPad::GetPad(0)->Mode < 0) + CPad::GetPad(0)->Mode = 3; + SaveSettings(); + break; +#endif + case MENUACTION_RADIO: + ChangeRadioStation(changeAmount); + break; + case MENUACTION_RADARMODE: + m_PrefsRadarMode += changeAmount; + if (m_PrefsRadarMode < 0) + m_PrefsRadarMode = 2; + if (m_PrefsRadarMode > 2) + m_PrefsRadarMode = 0; + break; +#ifdef ASPECT_RATIO_SCALE + case MENUACTION_WIDESCREEN: + if (changeAmount > 0) { + m_PrefsUseWideScreen++; + if (m_PrefsUseWideScreen > AR_MAX - 1) + m_PrefsUseWideScreen = 0; + } else { + m_PrefsUseWideScreen--; + if (m_PrefsUseWideScreen < 0) + m_PrefsUseWideScreen = AR_MAX - 1; + } + SaveSettings(); + break; +#endif + case MENUACTION_SCREENRES: + if (m_bGameNotLoaded) { + RwChar** videoMods = _psGetVideoModeList(); + if (changeAmount > 0) { + do { + ++m_nDisplayVideoMode; + + if (m_nDisplayVideoMode >= _psGetNumVideModes()) + m_nDisplayVideoMode = 0; + } while (!videoMods[m_nDisplayVideoMode]); + } else { + do { + --m_nDisplayVideoMode; + + if (m_nDisplayVideoMode < 0) + m_nDisplayVideoMode = _psGetNumVideModes() - 1; + } while (!videoMods[m_nDisplayVideoMode]); + } + } + break; + case MENUACTION_AUDIOHW: + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { + m_nPrefsAudio3DProviderIndex += changeAmount; + + bool checkIfForbidden = true; + while (checkIfForbidden) { + checkIfForbidden = false; + + if (m_nPrefsAudio3DProviderIndex < -1) + m_nPrefsAudio3DProviderIndex = DMAudio.GetNum3DProvidersAvailable() - 1; + else if (m_nPrefsAudio3DProviderIndex > DMAudio.GetNum3DProvidersAvailable() - 1) + m_nPrefsAudio3DProviderIndex = -1; + + // what a retarded move... + if (m_nPrefsAudio3DProviderIndex != -1) { + char* provider = DMAudio.Get3DProviderName(m_nPrefsAudio3DProviderIndex); + strupr(provider); + if (!strcmp(provider, "MILES FAST 2D POSITIONAL AUDIO")) { + m_nPrefsAudio3DProviderIndex += changeAmount; + checkIfForbidden = true; + + } else if (!strcmp(provider, "AUREAL A3D 2.0 (TM)")) { + m_nPrefsAudio3DProviderIndex += changeAmount; + checkIfForbidden = true; + + } else if (!strcmp(provider, "AUREAL A3D INTERACTIVE (TM)")) { + m_nPrefsAudio3DProviderIndex += changeAmount; + checkIfForbidden = true; + } + } + } + } + break; + case MENUACTION_SPEAKERCONF: + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { + m_PrefsSpeakers -= changeAmount; + m_PrefsSpeakers = clamp(m_PrefsSpeakers, 0, 2); + DMAudio.SetSpeakerConfig(m_PrefsSpeakers); + SaveSettings(); + } + break; + case MENUACTION_CTRLMETHOD: + m_ControlMethod = !m_ControlMethod; + CCamera::m_bUseMouse3rdPerson = !m_ControlMethod; + SaveSettings(); + break; +#ifdef CUSTOM_FRONTEND_OPTIONS + case MENUACTION_CFO_SELECT: + case MENUACTION_CFO_DYNAMIC: + CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption]; + if (option.m_Action == MENUACTION_CFO_SELECT) { + if (option.m_CFOSelect->disableIfGameLoaded && !m_bGameNotLoaded) + break; + + if (changeAmount > 0) { + option.m_CFOSelect->displayedValue++; + if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts) + option.m_CFOSelect->displayedValue = 0; + } else { + option.m_CFOSelect->displayedValue--; + if (option.m_CFOSelect->displayedValue < 0) + option.m_CFOSelect->displayedValue = option.m_CFOSelect->numRightTexts - 1; + } + if (!option.m_CFOSelect->onlyApplyOnEnter) { + int8 oldValue = *option.m_CFO->value; + + *option.m_CFO->value = option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue; + + // Now everything is saved in .ini, and LOAD_INI_SETTINGS is fundamental for CFO + // if (option.m_CFOSelect->save) + SaveSettings(); + + if (option.m_CFOSelect->displayedValue != oldValue && option.m_CFOSelect->changeFunc) + option.m_CFOSelect->changeFunc(oldValue, option.m_CFOSelect->displayedValue); + } + } else if (option.m_Action == MENUACTION_CFO_DYNAMIC && option.m_CFODynamic->buttonPressFunc) { + option.m_CFODynamic->buttonPressFunc(changeAmount > 0 ? FEOPTION_ACTION_RIGHT : FEOPTION_ACTION_LEFT); + } + break; +#endif + } + CheckSliderMovement(changeAmount); + ProcessOnOffMenuOptions(); + if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { + if (changeAmount < 1) { + m_nSelectedContSetupColumn = CONTSETUP_PED_COLUMN; + } else { + m_nSelectedContSetupColumn = CONTSETUP_VEHICLE_COLUMN; + } + } + } +} + +void +CMenuManager::ProcessOnOffMenuOptions() +{ + switch (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action) { +#ifdef GAMEPAD_MENU + case MENUACTION_CTRLVIBRATION: + m_PrefsUseVibration = !m_PrefsUseVibration; + if (m_PrefsUseVibration) { + CPad::GetPad(0)->StartShake(350, 150); + TimeToStopPadShaking = CTimer::GetTimeInMillisecondsPauseMode() + 500; + } + SaveSettings(); + break; +#endif + case MENUACTION_INVERTPADY: + CPad::bInvertLook4Pad = !CPad::bInvertLook4Pad; + SaveSettings(); // FIX: Why don't SaveSettings? Because of it's an hidden option? :( + break; + case MENUACTION_CTRLDISPLAY: + m_DisplayControllerOnFoot = !m_DisplayControllerOnFoot; + break; + case MENUACTION_FRAMESYNC: + m_PrefsVsyncDisp = !m_PrefsVsyncDisp; + SaveSettings(); // FIX: Again... This makes me very unhappy + break; + case MENUACTION_FRAMELIMIT: + m_PrefsFrameLimiter = !m_PrefsFrameLimiter; + SaveSettings(); + break; + case MENUACTION_TRAILS: + CMBlur::BlurOn = !CMBlur::BlurOn; + SaveSettings(); + break; + case MENUACTION_SUBTITLES: + m_PrefsShowSubtitles = !m_PrefsShowSubtitles; + SaveSettings(); + break; +#ifndef ASPECT_RATIO_SCALE + case MENUACTION_WIDESCREEN: + m_PrefsUseWideScreen = !m_PrefsUseWideScreen; + SaveSettings(); + break; +#endif + case MENUACTION_LEGENDS: + m_PrefsShowLegends = !m_PrefsShowLegends; + break; + case MENUACTION_HUD: + m_PrefsShowHud = !m_PrefsShowHud; + SaveSettings(); + break; +#ifdef LEGACY_MENU_OPTIONS + case MENUACTION_SETDBGFLAG: + CTheScripts::InvertDebugFlag(); + break; + case MENUACTION_SWITCHBIGWHITEDEBUGLIGHT: + gbBigWhiteDebugLightSwitchedOn = !gbBigWhiteDebugLightSwitchedOn; + break; + case MENUACTION_COLLISIONPOLYS: + gbShowCollisionPolys = !gbShowCollisionPolys; + break; +#endif + case MENUACTION_SHOWHEADBOB: + TheCamera.m_bHeadBob = !TheCamera.m_bHeadBob; + SaveSettings(); + break; + case MENUACTION_INVVERT: + MousePointerStateHelper.bInvertVertically = !MousePointerStateHelper.bInvertVertically; + SaveSettings(); + break; + case MENUACTION_DYNAMICACOUSTIC: + m_PrefsDMA = !m_PrefsDMA; + DMAudio.SetDynamicAcousticModelingStatus(m_PrefsDMA); + SaveSettings(); + break; + case MENUACTION_MOUSESTEER: + if (m_ControlMethod == CONTROL_STANDARD) { + CVehicle::m_bDisableMouseSteering = !CVehicle::m_bDisableMouseSteering; + SaveSettings(); + } + break; + } +} + +void +CMenuManager::RequestFrontEndShutDown() +{ + m_bShutDownFrontEndRequested = true; +} + +void +CMenuManager::RequestFrontEndStartUp() +{ + m_bStartUpFrontEndRequested = true; +} + +void +CMenuManager::ResetHelperText() +{ + m_nHelperTextMsgId = 0; + m_nHelperTextAlpha = 300; +} + +void +CMenuManager::SetHelperText(int text) +{ + m_nHelperTextMsgId = text; + m_nHelperTextAlpha = 300; +} + +float +CMenuManager::StretchX(float x) +{ + if (SCREEN_WIDTH == DEFAULT_SCREEN_WIDTH) + return x; + else + // We won't make this SCREEN_SCALE, because many cases relies on stretching and we want the code to be portable. + // Instead we will use MENU_X_LEFT_ALIGNED or SCREEN_SCALE_X when needed. + return SCREEN_STRETCH_X(x); +} + +float CMenuManager::StretchY(float y) +{ + if (SCREEN_HEIGHT == DEFAULT_SCREEN_HEIGHT) + return y; + else + return SCREEN_STRETCH_Y(y); +} + +#ifdef XBOX_MESSAGE_SCREEN +void +CMenuManager::CloseDialog(void) +{ + // We don't have this on PC GXT :shrug: + static wchar* gameSaved = AllocUnicode("Game saved successfully!"); + + if (m_bSaveWasSuccessful && DialogTextCmp("FESZ_WR")) { + m_bSaveWasSuccessful = false; // i don't know where XBOX resets that + m_pDialogText = gameSaved; + SetDialogTimer(1000); + ProcessDialogTimer(); + } else { + ToggleDialog(false); + } + +} + +void +CMenuManager::ProcessDialogTimer(void) +{ + if (!m_bDialogOpen || m_nDialogHideTimer == 0) + return; + + // Also XBOX has unified time source for in-game/menu, but we don't have that + if (m_bMenuActive && CTimer::GetTimeInMilliseconds() > m_nDialogHideTimer || !m_bMenuActive && CTimer::GetTimeInMillisecondsPauseMode() > m_nDialogHideTimerPauseMode) { + + // This is originally activePage.funcs->closePage() + CloseDialog(); + } +} + +void +CMenuManager::SetDialogTimer(uint32 timer) +{ + // XBOX iterates some page list(actives?) and then sets timer variable of specified page to specified value. We only have dialog right now. + // Also XBOX has unified time source for in-game/menu, but we don't have that, thus 2 timer variables... + + m_nDialogHideTimer = CTimer::GetTimeInMilliseconds() + timer; + m_nDialogHideTimerPauseMode = CTimer::GetTimeInMillisecondsPauseMode() + timer; +} + +void +CMenuManager::SetDialogText(const char* key) +{ + // There are many things going around here, idk why + m_pDialogText = TheText.Get(key); +} + +bool +CMenuManager::DialogTextCmp(const char* key) +{ + wchar *value = TheText.Get(key); + wchar *i = m_pDialogText; + for (; *i != '\0' && *value != '\0'; i++, value++) { + if (*i != *value) + return false; + } + return *i == '\0' && *value == '\0'; +} + +void +CMenuManager::ToggleDialog(bool toggle) +{ + // This originally calls some mysterious function on enable and close CB on disable, along with decreasing some counter. Which is no use for dialog + + // XBOX doesn't do that + if (toggle) + m_nDialogHideTimer = 0; + + m_bDialogOpen = toggle; +} + +void +DrawDialogBg(float offset, uint8 alpha) +{ + CSprite2d::Draw2DPolygon(SCALE_AND_CENTER_X(84.f + offset), MENU_Y(126.f + offset), + SCALE_AND_CENTER_X(512.f + offset), MENU_Y(109.f + offset), + SCALE_AND_CENTER_X(100.f + offset), MENU_Y(303.f + offset), + SCALE_AND_CENTER_X(474.f + offset), MENU_Y(311.f + offset), CRGBA(107, 193, 236, alpha)); + CSprite2d::Draw2DPolygon(SCALE_AND_CENTER_X(523.f + offset), MENU_Y(108.f + offset), + SCALE_AND_CENTER_X(542.f + offset), MENU_Y(107.f + offset), + SCALE_AND_CENTER_X(485.f + offset), MENU_Y(310.f + offset), + SCALE_AND_CENTER_X(516.f + offset), MENU_Y(311.f + offset), CRGBA(107, 193, 236, alpha)); +} + +void +CMenuManager::DrawOverlays(void) +{ + // This is stripped to show only Dialog box, XBOX does much more in here. + + if (!m_bDialogOpen) + return; + + DefinedState(); + + CSprite2d::DrawRect(CRect(0, SCREEN_HEIGHT, SCREEN_WIDTH, 0), CRGBA(0, 0, 0, 160)); + + // Ofc this is not hardcoded like that on Xbox, it should be a texture + DrawDialogBg(20.f, 160); // shadow + DrawDialogBg(0.f, 255); + + CFont::SetBackgroundOff(); + CFont::SetPropOn(); + CFont::SetJustifyOn(); + CFont::SetBackGroundOnlyTextOn(); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetCentreSize(SCREEN_SCALE_X(380.0f)); + CFont::SetCentreOn(); + CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, 255)); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + // Both of those are 0.9 on Xbox, which is ofcouse wrong... + CFont::SetScale(SCREEN_SCALE_X(BIGTEXT_X_SCALE), SCREEN_SCALE_Y(BIGTEXT_Y_SCALE)); + + int x = SCREEN_WIDTH / 2.f - SCREEN_SCALE_X(30.0f); + int y = SCREEN_HEIGHT / 2.f - SCREEN_SCALE_Y(30.0f); + int numOfLines = CFont::GetNumberLines(x, y, m_pDialogText); + CFont::PrintString(x, y - SCREEN_SCALE_Y(numOfLines / 2.f), m_pDialogText); + CFont::DrawFonts(); +} +#endif + +void +CMenuManager::ProcessFileActions() +{ + switch (m_nCurrScreen) { + case MENUPAGE_LOADING_IN_PROGRESS: + if (CheckSlotDataValid(m_nCurrSaveSlot)) { +#ifdef USE_DEBUG_SCRIPT_LOADER + scriptToLoad = 0; +#endif + +#ifdef XBOX_MESSAGE_SCREEN + SetDialogText("FELD_WR"); + ToggleDialog(true); +#else + if (!m_bGameNotLoaded) + MessageScreen("FELD_WR", true); +#endif + DoSettingsBeforeStartingAGame(); + m_bWantToLoad = true; + } else + SwitchToNewScreen(MENUPAGE_NEW_GAME); + + break; + case MENUPAGE_DELETING_IN_PROGRESS: + { + static bool waitedForScreen = false; + + if (waitedForScreen) { + bool SlotPopulated = false; + if (PcSaveHelper.DeleteSlot(m_nCurrSaveSlot)) { + PcSaveHelper.PopulateSlotInfo(); + SlotPopulated = true; + } + + if (SlotPopulated) { + SwitchToNewScreen(MENUPAGE_DELETE_SUCCESSFUL); + } else { + SwitchToNewScreen(MENUPAGE_SAVE_CUSTOM_WARNING); + strncpy(aScreens[m_nCurrScreen].m_ScreenName, "FES_DEL", 8); + strncpy(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName, "FES_DEE", 8); + } + waitedForScreen = false; + } else if (m_nMenuFadeAlpha >= 255) + waitedForScreen = true; + + break; + } + case MENUPAGE_SAVING_IN_PROGRESS: + { +#ifdef XBOX_MESSAGE_SCREEN + if (m_bDialogOpen && DialogTextCmp("FESZ_WR")) { + PauseModeTime startTime = CTimer::GetTimeInMillisecondsPauseMode(); + int8 SaveSlot = PcSaveHelper.SaveSlot(m_nCurrSaveSlot); + PcSaveHelper.PopulateSlotInfo(); + + // Original code, but we don't want redundant saving text if it doesn't +#if 0 + CTimer::Update(); // not on Xbox, who updates it? + + // it compensates the lag to show saving text always one second... how cute + int dialogDur = Max(1, startTime - CTimer::GetTimeInMillisecondsPauseMode() + 1000); +#else + int dialogDur = 1; +#endif + + if (SaveSlot) { + // error. PC code + ToggleDialog(false); + SwitchToNewScreen(MENUPAGE_SAVE_CUSTOM_WARNING); + strncpy(aScreens[m_nCurrScreen].m_ScreenName, "FET_SG", 8); + strncpy(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName, "FES_CMP", 8); + + } else { + m_bSaveWasSuccessful = true; + SetDialogTimer(dialogDur); + ProcessDialogTimer(); + RequestFrontEndShutDown(); + } + + } else { + SetDialogText("FESZ_WR"); + ToggleDialog(true); + } +#else + static bool waitedForScreen = false; + + if (waitedForScreen) { + int8 SaveSlot = PcSaveHelper.SaveSlot(m_nCurrSaveSlot); + PcSaveHelper.PopulateSlotInfo(); + if (SaveSlot) { + SwitchToNewScreen(MENUPAGE_SAVE_CUSTOM_WARNING); + strncpy(aScreens[m_nCurrScreen].m_ScreenName, "FET_SG", 8); + strncpy(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName, "FES_CMP", 8); + } else + SwitchToNewScreen(MENUPAGE_SAVE_SUCCESSFUL); + + waitedForScreen = false; + } else if (m_nMenuFadeAlpha >= 255) + waitedForScreen = true; +#endif + break; + } + } +} + +void +CMenuManager::SwitchMenuOnAndOff() +{ + if (!TheCamera.m_WideScreenOn) { + + // Reminder: You need REGISTER_START_BUTTON defined to make it work. + if ((CPad::GetPad(0)->GetStartJustDown() || CPad::GetPad(0)->GetEscapeJustDown()) + && (!m_bMenuActive || m_nCurrScreen == MENUPAGE_PAUSE_MENU || m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT || m_nCurrScreen == MENUPAGE_SAVE_CHEAT_WARNING) + || m_bShutDownFrontEndRequested || m_bStartUpFrontEndRequested +#ifdef REGISTER_START_BUTTON + || CPad::GetPad(0)->GetStartJustDown() && !m_bGameNotLoaded +#endif + ) { + + if (m_nCurrScreen != MENUPAGE_LOADING_IN_PROGRESS +#ifdef XBOX_MESSAGE_SCREEN + && m_nCurrScreen != MENUPAGE_SAVING_IN_PROGRESS +#endif + ) { + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + } + + if (m_bShutDownFrontEndRequested) + m_bMenuActive = false; + else if (m_bStartUpFrontEndRequested) + m_bMenuActive = true; + else + m_bMenuActive = !m_bMenuActive; + + if (m_bMenuActive) { + if (_InputMouseNeedsExclusive()) { + _InputShutdownMouse(); + _InputInitialiseMouse(false); + } + Initialise(); + LoadAllTextures(); +#ifdef FIX_BUGS + CPad::StopPadsShaking(); +#endif + } else { +#ifdef EXTENDED_COLOURFILTER + // we always expect CPostFX to be open + CMBlur::BlurOn = true; +#endif + if (CMBlur::BlurOn) + CMBlur::MotionBlurOpen(Scene.camera); + else + CMBlur::MotionBlurClose(); + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + if (_InputMouseNeedsExclusive()) { + _InputShutdownMouse(); + _InputInitialiseMouse(true); + } + + m_StatsScrollSpeed = 150.0f; +#ifdef FIX_BUGS + ThingsToDoBeforeLeavingPage(); +#endif + SaveSettings(); +#ifdef LOAD_INI_SETTINGS + SaveINIControllerSettings(); +#endif + pControlEdit = nil; + pEditString = nil; + DisplayComboButtonErrMsg = false; + m_bShutDownFrontEndRequested = false; + m_bStartUpFrontEndRequested = false; + m_bWaitingForNewKeyBind = false; + +#ifdef REGISTER_START_BUTTON + int16 start1 = CPad::GetPad(0)->PCTempJoyState.Start, start2 = CPad::GetPad(0)->PCTempKeyState.Start, + start3 = CPad::GetPad(0)->OldState.Start, start4 = CPad::GetPad(0)->NewState.Start; +#endif + CPad::GetPad(0)->Clear(false); + CPad::GetPad(1)->Clear(false); +#ifdef REGISTER_START_BUTTON + CPad::GetPad(0)->PCTempJoyState.Start = start1; + CPad::GetPad(0)->PCTempKeyState.Start = start2; + CPad::GetPad(0)->OldState.Start = start3; + CPad::GetPad(0)->NewState.Start = start4; +#endif + UnloadTextures(); + CTimer::EndUserPause(); + CTimer::Update(); + m_OnlySaveMenu = false; + } + } + } + + // Just entered the save/safe zone + if (m_bActivateSaveMenu) { + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + m_bActivateSaveMenu = false; + m_bMenuActive = true; + m_OnlySaveMenu = true; + + if (_InputMouseNeedsExclusive()) { + _InputShutdownMouse(); + _InputInitialiseMouse(false); + } + + Initialise(); + LoadAllTextures(); + + if (CPad::bHasPlayerCheated) { + m_nCurrScreen = MENUPAGE_SAVE_CHEAT_WARNING; + m_nCurrOption = 0; + } else { + m_nCurrScreen = MENUPAGE_CHOOSE_SAVE_SLOT; + m_nCurrOption = 8; + } + } + + m_bStartUpFrontEndRequested = false; + m_bShutDownFrontEndRequested = false; + +#ifdef GAMEPAD_MENU + // Reset pad shaking. + if (TimeToStopPadShaking && TimeToStopPadShaking < CTimer::GetTimeInMillisecondsPauseMode()) { + CPad::StopPadsShaking(); + TimeToStopPadShaking = 0; + } +#endif +} + +void +CMenuManager::UnloadTextures() +{ + if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) + DMAudio.StopFrontEndTrack(); + + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_STARTING, 0); + DMAudio.ChangeMusicMode(MUSICMODE_GAME); + if (m_bSpritesLoaded) { + printf("REMOVE frontend\n"); + int frontend = CTxdStore::FindTxdSlot("frontend1"); + for (int i = 0; i < 3; ++i) + m_aFrontEndSprites[i].Delete(); + + CTxdStore::RemoveTxd(frontend); + + if (!m_OnlySaveMenu) { + int frontend2 = CTxdStore::FindTxdSlot("frontend2"); + for (int i = 3; i < NUM_MENU_SPRITES; ++i) + m_aFrontEndSprites[i].Delete(); + + CTxdStore::RemoveTxd(frontend2); + +#ifdef GAMEPAD_MENU + // Unload controller txd + int frontend_controller = CTxdStore::FindTxdSlot("frontend_controller"); + if (frontend_controller != -1) + CTxdStore::RemoveTxd(frontend_controller); +#endif + } + + m_bSpritesLoaded = false; + } + m_OnlySaveMenu = false; + CUserDisplay::PlaceName.ProcessAfterFrontEndShutDown(); +} + +void +CMenuManager::WaitForUserCD() +{ + CSprite2d *splash; + char *splashscreen = nil; + + splash = LoadSplash(splashscreen); + + if (RsGlobal.quit) + return; + + HandleExit(); + CPad::UpdatePads(); + MessageScreen("NO_PCCD", true); + + if (CPad::GetPad(0)->GetEscapeJustDown()) { + m_bQuitGameNoCD = true; + RsEventHandler(rsQUITAPP, nil); + } +} + +void +CMenuManager::DrawQuitGameScreen(void) +{ + static int32 exitSignalTimer = 0; + +#ifdef FIX_BUGS + int alpha = clamp(m_nMenuFadeAlpha, 0, 255); +#else + int alpha = m_nMenuFadeAlpha; +#endif + +#ifndef MUCH_SHORTER_OUTRO_SCREEN + static PauseModeTime lastTickIncrease = 0; + if (alpha == 255 && CTimer::GetTimeInMillisecondsPauseMode() - lastTickIncrease > 10) { + exitSignalTimer++; + lastTickIncrease = CTimer::GetTimeInMillisecondsPauseMode(); + } +#else + static PauseModeTime firstTick = CTimer::GetTimeInMillisecondsPauseMode(); + if (alpha == 255 && CTimer::GetTimeInMillisecondsPauseMode() - firstTick > 750) { + exitSignalTimer = 150; + } +#endif + static CSprite2d *splash = nil; + + if (splash == nil) + splash = LoadSplash("OUTRO"); + + m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(SCREEN_STRETCH_X(28.0f), MENU_Y(8.0f), SCREEN_STRETCH_X(27.0f) + MENU_X(130.f), MENU_Y(138.0f)), CRGBA(255, 255, 255, 255 - alpha)); + + // Or we can see menu background from sides +#ifdef ASPECT_RATIO_SCALE + CSprite2d::DrawRect(CRect(0, 0, MENU_X_LEFT_ALIGNED(0.f), SCREEN_HEIGHT), CRGBA(0, 0, 0, alpha)); + CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(0.f), 0, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, alpha)); +#endif + + splash->Draw(CRect(MENU_X_LEFT_ALIGNED(0.f), 0, MENU_X_RIGHT_ALIGNED(0.f), SCREEN_HEIGHT), CRGBA(255, 255, 255, alpha)); + if (alpha == 255 && exitSignalTimer == 150) + RsEventHandler(rsQUITAPP, nil); + + m_bShowMouse = false; + m_AllowNavigation = false; +} + +void +CMenuManager::PrintMap(void) +{ + m_bMenuMapActive = true; + CRadar::InitFrontEndMap(); + + // Because m_fMapSize is half of the map length(hence * 2), and map consists of 3x3 tiles(hence / 3). + float halfTile = m_fMapSize * 2.f / 3.f / 2.f; + + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + + if (SCREEN_WIDTH >= m_fMapCenterX - m_fMapSize || SCREEN_HEIGHT >= m_fMapCenterY - m_fMapSize) { + m_aFrontEndSprites[MENUSPRITE_MAPTOP01].Draw(CRect(m_fMapCenterX - m_fMapSize, m_fMapCenterY - m_fMapSize, + m_fMapCenterX - halfTile, m_fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); + } + + if (SCREEN_WIDTH >= m_fMapCenterX - halfTile || SCREEN_HEIGHT >= m_fMapCenterY - m_fMapSize) { + m_aFrontEndSprites[MENUSPRITE_MAPTOP02].Draw(CRect(m_fMapCenterX - halfTile, m_fMapCenterY - m_fMapSize, + m_fMapCenterX + halfTile, m_fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); + } + + if (SCREEN_WIDTH >= m_fMapCenterX + halfTile || SCREEN_HEIGHT >= m_fMapCenterY - m_fMapSize) { + m_aFrontEndSprites[MENUSPRITE_MAPTOP03].Draw(CRect(m_fMapCenterX + halfTile, m_fMapCenterY - m_fMapSize, + m_fMapCenterX + m_fMapSize, m_fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); + } + + if (SCREEN_WIDTH >= m_fMapCenterX - m_fMapSize || SCREEN_HEIGHT >= m_fMapCenterY - halfTile) { + m_aFrontEndSprites[MENUSPRITE_MAPMID01].Draw(CRect(m_fMapCenterX - m_fMapSize, m_fMapCenterY - halfTile, + m_fMapCenterX - halfTile, m_fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); + } + + if (SCREEN_WIDTH >= m_fMapCenterX - halfTile || SCREEN_HEIGHT >= m_fMapCenterY - halfTile) { + m_aFrontEndSprites[MENUSPRITE_MAPMID02].Draw(CRect(m_fMapCenterX - halfTile, m_fMapCenterY - halfTile, + m_fMapCenterX + halfTile, m_fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); + } + + if (SCREEN_WIDTH >= m_fMapCenterX + halfTile || SCREEN_HEIGHT >= m_fMapCenterY - halfTile) { + m_aFrontEndSprites[MENUSPRITE_MAPMID03].Draw(CRect(m_fMapCenterX + halfTile, m_fMapCenterY - halfTile, + m_fMapCenterX + m_fMapSize, m_fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); + } + + if (SCREEN_WIDTH >= m_fMapCenterX - m_fMapSize || SCREEN_HEIGHT >= m_fMapCenterY + halfTile) { + m_aFrontEndSprites[MENUSPRITE_MAPBOT01].Draw(CRect(m_fMapCenterX - m_fMapSize, m_fMapCenterY + halfTile, + m_fMapCenterX - halfTile, m_fMapCenterY + m_fMapSize), CRGBA(255, 255, 255, FadeIn(255))); + } + + if (SCREEN_WIDTH >= m_fMapCenterX - halfTile || SCREEN_HEIGHT >= m_fMapCenterY + halfTile) { + m_aFrontEndSprites[MENUSPRITE_MAPBOT02].Draw(CRect(m_fMapCenterX - halfTile, m_fMapCenterY + halfTile, + m_fMapCenterX + halfTile, m_fMapCenterY + m_fMapSize), CRGBA(255, 255, 255, FadeIn(255))); + } + + if (SCREEN_WIDTH >= m_fMapCenterX + halfTile || SCREEN_HEIGHT >= m_fMapCenterY + halfTile) { + m_aFrontEndSprites[MENUSPRITE_MAPBOT03].Draw(CRect(m_fMapCenterX + halfTile, m_fMapCenterY + halfTile, + m_fMapCenterX + m_fMapSize, m_fMapCenterY + m_fMapSize), CRGBA(255, 255, 255, FadeIn(255))); + } + + CRadar::DrawBlips(); + if (m_PrefsShowLegends) { + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(40.0f)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(84.0f)); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetCentreOn(); + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(SCREEN_SCALE_X(0.65f), SCREEN_SCALE_Y(0.95f)); + + int secondColumnStart = (CRadar::MapLegendCounter - 1) / 2; + int boxBottom = MENU_Y(100.0f); + + // + 3, because we want 19*3 px padding + for (int i = 0; i < secondColumnStart + 3; i++) { + boxBottom += MENU_Y(19.f); + } + + CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(95.0f), MENU_Y(100.0f), MENU_X_LEFT_ALIGNED(555.f), boxBottom), + CRGBA(0, 0, 0, FadeIn(190))); + + CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), MENU_Y(102.0f), TheText.Get("FE_MLG")); + CFont::SetRightJustifyOff(); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + if (m_PrefsLanguage == LANGUAGE_AMERICAN) + CFont::SetScale(SCREEN_SCALE_X(0.55f), SCREEN_SCALE_Y(0.55f)); + else + CFont::SetScale(SCREEN_SCALE_X(0.45f), SCREEN_SCALE_Y(0.55f)); + + CFont::SetColor(CRGBA(225, 225, 225, FadeIn(255))); + CFont::SetDropShadowPosition(0); + + int y = MENU_Y(127.0f); + int x = MENU_X_LEFT_ALIGNED(160.0f); + + for (int16 i = 0; i < CRadar::MapLegendCounter; i++) { + CRadar::DrawLegend(x, y, CRadar::MapLegendList[i]); + + if (i == secondColumnStart) { + x = MENU_X_LEFT_ALIGNED(350.0f); + y = MENU_Y(127.0f); + } else { + y += MENU_Y(19.0f); + } + } + } + +#ifdef MAP_ENHANCEMENTS + if (m_nMenuFadeAlpha != 255 && !m_bShowMouse) { + mapCrosshair.x = SCREEN_WIDTH / 2; + mapCrosshair.y = SCREEN_HEIGHT / 2; + } else if (m_bShowMouse) { + mapCrosshair.x = m_nMousePosX; + mapCrosshair.y = m_nMousePosY; + } + + CSprite2d::DrawRect(CRect(mapCrosshair.x - MENU_X(1.0f), 0.0f, + mapCrosshair.x + MENU_X(1.0f), SCREEN_HEIGHT), + CRGBA(0, 0, 0, 150)); + CSprite2d::DrawRect(CRect(0.0f, mapCrosshair.y + MENU_X(1.0f), + SCREEN_WIDTH, mapCrosshair.y - MENU_X(1.0f)), + CRGBA(0, 0, 0, 150)); + +#endif + m_bMenuMapActive = false; + + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN)); + DisplayHelperText("FEH_MPH"); +} + +void +CMenuManager::ChangeRadioStation(int8 increaseBy) +{ + if (m_ScrollRadioBy != 0) + return; + + m_PrefsRadioStation += increaseBy; + m_ScrollRadioBy = increaseBy; + if (m_ScrollRadioBy == 1) { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0); + m_LeftMostRadioX = MENU_X_LEFT_ALIGNED(MENURADIO_ICON_FIRST_X); + } else { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0); + m_LeftMostRadioX = MENU_X_LEFT_ALIGNED(MENURADIO_ICON_FIRST_X - (2 * MENURADIO_ICON_SIZE)); + } + + if (DMAudio.IsMP3RadioChannelAvailable()) { + if (m_PrefsRadioStation < WILDSTYLE) + m_PrefsRadioStation = USERTRACK; + if (m_PrefsRadioStation > USERTRACK) + m_PrefsRadioStation = WILDSTYLE; + } else { + if (m_PrefsRadioStation < WILDSTYLE) + m_PrefsRadioStation = WAVE; + if (m_PrefsRadioStation > WAVE) + m_PrefsRadioStation = WILDSTYLE; + } + DMAudio.StopFrontEndTrack(); + DMAudio.PlayFrontEndSound(SOUND_RADIO_CHANGE, 0); +} + +#if 0 +uint8 CMenuManager::GetNumberOfMenuOptions() +{ + uint8 Rows = -1; + for (int i = 0; i < NUM_MENUROWS; i++) { + if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_NOTHING) + break; + + ++Rows; + } + return Rows; +} +#endif + +#ifdef GAMEPAD_MENU +const char* controllerTypesPaths[] = { + "MODELS/FRONTEND_DS2.TXD", + "MODELS/FRONTEND_DS3.TXD", + "MODELS/FRONTEND_DS4.TXD", + "MODELS/FRONTEND_X360.TXD", + "MODELS/FRONTEND_XONE.TXD", +}; + +void +CMenuManager::PrintController(void) +{ + // Don't print anything if controller texture is missing + if (!m_aFrontEndSprites[MENUSPRITE_CONTROLLER].m_pTexture) return; + + const float scale = 0.9f; + const float CONTROLLER_SIZE_X = 235.2f; + const float CONTROLLER_SIZE_Y = 175.2f; + const float CONTROLLER_POS_X = (DEFAULT_SCREEN_WIDTH - CONTROLLER_SIZE_X) / 2.0f; + const float CONTROLLER_POS_Y = 220.0f; + + float centerX = CONTROLLER_POS_X + CONTROLLER_SIZE_X / 2; + float centerY = CONTROLLER_POS_Y + CONTROLLER_SIZE_Y / 2; + +#define X(f) ((f)*scale + centerX) +#define Y(f) ((f)*scale + centerY) + + m_aFrontEndSprites[MENUSPRITE_CONTROLLER].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, FadeIn(255))); + if (m_DisplayControllerOnFoot) { + if ((int)CTimer::GetTimeInMillisecondsPauseMode() & 0x400) + m_aFrontEndSprites[MENUSPRITE_ARROWS1].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, FadeIn(255))); + else + m_aFrontEndSprites[MENUSPRITE_ARROWS3].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, FadeIn(255))); + } + else { + if ((int)CTimer::GetTimeInMillisecondsPauseMode() & 0x400) + m_aFrontEndSprites[MENUSPRITE_ARROWS2].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, FadeIn(255))); + else + m_aFrontEndSprites[MENUSPRITE_ARROWS4].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, FadeIn(255))); + } + + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.9f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.9f)); // X + + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetDropShadowPosition(0); + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetWrapx(SCREEN_WIDTH); + + float TEXT_L2_X = 85.0f + CONTROLLER_POS_X - centerX, TEXT_L2_Y = -14.0f + CONTROLLER_POS_Y - centerY; + float TEXT_L1_X = -4.0f + CONTROLLER_POS_X - centerX, TEXT_L1_Y = 27.0f + CONTROLLER_POS_Y - centerY, TEXT_L1_Y_VEH = 3.0f + TEXT_L1_Y; + float TEXT_DPAD_X = -4.0f + CONTROLLER_POS_X - centerX, TEXT_DPAD_Y = 67.0f + CONTROLLER_POS_Y - centerY; + float TEXT_LSTICK_X = -4.0f + CONTROLLER_POS_X - centerX, TEXT_LSTICK_Y = 97.0f + CONTROLLER_POS_Y - centerY; + float TEXT_SELECT_X = 170.0f + CONTROLLER_POS_X - centerX, TEXT_SELECT_Y = 141.0f + CONTROLLER_POS_Y - centerY; + float TEXT_START_X = 130.0f + CONTROLLER_POS_X - centerX, TEXT_START_Y = 128.0f + CONTROLLER_POS_Y - centerY; + float TEXT_R2_X = 164.0f + CONTROLLER_POS_X - centerX, TEXT_R2_Y = -14.0f + CONTROLLER_POS_Y - centerY; + float TEXT_R1_X = 242.0f + CONTROLLER_POS_X - centerX, TEXT_R1_Y = 27.0f + CONTROLLER_POS_Y - centerY; + + float TEXT_SQUARE_X = 147.0f + CONTROLLER_POS_X - centerX, TEXT_SQUARE_Y = 30.0f + CONTROLLER_POS_Y - centerY; + float TEXT_TRIANGLE_X = 242.0f + CONTROLLER_POS_X - centerX, TEXT_TRIANGLE_Y = 55.0f + CONTROLLER_POS_Y - centerY; + float TEXT_CIRCLE_X = 242.0f + CONTROLLER_POS_X - centerX, TEXT_CIRCLE_Y = 67.0f + CONTROLLER_POS_Y - centerY; + float TEXT_CROSS_X = 242.0f + CONTROLLER_POS_X - centerX, TEXT_CROSS_Y = 80.0f + CONTROLLER_POS_Y - centerY; + float TEXT_RSTICK_X = 242.0f + CONTROLLER_POS_X - centerX, TEXT_RSTICK_Y = 97.0f + CONTROLLER_POS_Y - centerY; + float TEXT_R3_X = 242.0f + CONTROLLER_POS_X - centerX, TEXT_R3_Y = 110.0f + CONTROLLER_POS_Y - centerY; + float TEXT_L3_X = 94.0f + CONTROLLER_POS_X - centerX, TEXT_L3_Y = 162.0f + CONTROLLER_POS_Y - centerY; + float TEXT_L2R2_X = 120.0f + CONTROLLER_POS_X - centerX, TEXT_L2R2_Y = -4.0f + CONTROLLER_POS_Y - centerY; + + switch (m_PrefsControllerType) + { + case CONTROLLER_DUALSHOCK4: + TEXT_L1_Y += 7.0f; + TEXT_L1_Y_VEH = TEXT_L1_Y; + TEXT_R1_Y += 7.0f; + TEXT_TRIANGLE_Y -= 1.0f; + TEXT_CIRCLE_Y -= 1.0f; + TEXT_CROSS_Y -= 1.0f; + TEXT_RSTICK_Y -= 4.0f; + TEXT_R3_Y -= 4.0f; + TEXT_DPAD_Y -= 2.0f; + TEXT_LSTICK_Y -= 6.0f; + TEXT_L3_X -= 2.0f; + break; + case CONTROLLER_XBOXONE: + TEXT_L2_X -= 2.0f; + TEXT_R2_X += 2.0f; + TEXT_L1_Y += 15.0f; + TEXT_L1_Y_VEH = TEXT_L1_Y; + TEXT_R1_Y += 15.0f; + TEXT_TRIANGLE_Y += 4.0f; + TEXT_CIRCLE_Y += 4.0f; + TEXT_CROSS_Y += 4.0f; + TEXT_RSTICK_Y += 1.0f; + TEXT_R3_Y += 1.0f; + TEXT_DPAD_Y += 29.0f; + TEXT_LSTICK_Y -= 20.0f; + TEXT_L3_X -= 36.0f; + TEXT_L2R2_Y += 5.0f; + TEXT_SELECT_X += 4.0f; + break; + case CONTROLLER_XBOX360: + TEXT_L2_X += 8.0f; + TEXT_R2_X -= 8.0f; + TEXT_L1_Y += 15.0f; + TEXT_L1_Y_VEH = TEXT_L1_Y; + TEXT_R1_Y += 15.0f; + TEXT_TRIANGLE_Y += 4.0f; + TEXT_CIRCLE_Y += 4.0f; + TEXT_CROSS_Y += 4.0f; + TEXT_RSTICK_Y += 4.0f; + TEXT_R3_Y += 4.0f; + TEXT_DPAD_Y += 30.0f; + TEXT_LSTICK_Y -= 19.0f; + TEXT_L3_X -= 36.0f; + TEXT_L2R2_Y += 5.0f; + TEXT_SELECT_X += 3.0f; + break; + }; + + if (m_DisplayControllerOnFoot) { + switch (CPad::GetPad(0)->Mode) { + case 0: + CFont::SetRightJustifyOn(); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + TEXT_L2_X -= 45.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)) - SCREEN_SCALE_X(85)); + break; + default: + CFont::SetRightJustifyWrap(0); + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_CWL")); + CFont::SetRightJustifyWrap(0); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get("FEC_LOF")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_MOV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_MOV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_CR3")); + CFont::SetRightJustifyOn(); + switch (m_PrefsLanguage) + { + case LANGUAGE_GERMAN: + TEXT_SELECT_X += 20.0f; + break; + case LANGUAGE_SPANISH: + TEXT_SELECT_X += 15.0f; + break; + default: + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + TEXT_R2_X += 30.0f; + CFont::SetJustifyOff(); + CFont::SetWrapx(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)) + SCREEN_SCALE_X(120)); + break; + default: + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_CWR")); + CFont::SetJustifyOn(); + CFont::SetWrapx(SCREEN_WIDTH); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_TAR")); + CFont::SetRightJustifyOn(); + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_JUM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_ENV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_ATT")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_RUN")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_FPC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_LB3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get("FEC_R3")); + break; + case 1: + CFont::SetRightJustifyOn(); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + TEXT_L2_X -= 45.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)) - SCREEN_SCALE_X(85)); + break; + default: + CFont::SetRightJustifyWrap(0); + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_CWL")); + CFont::SetRightJustifyWrap(0); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get("FEC_LOF")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_MOV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_CR3")); + switch (m_PrefsLanguage) + { + case LANGUAGE_GERMAN: + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_NA")); + break; + default: + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X - 50)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_NA")); + break; + } + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + TEXT_R2_X += 30.0f; + CFont::SetJustifyOff(); + CFont::SetWrapx(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)) + SCREEN_SCALE_X(120)); + break; + default: + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_CWR")); + CFont::SetJustifyOn(); + CFont::SetWrapx(SCREEN_WIDTH); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_TAR")); + CFont::SetRightJustifyOn(); + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_JUM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_ENV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_ATT")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_RUN")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_FPC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_LB3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get("FEC_R3")); + break; + case 2: + CFont::SetRightJustifyOn(); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + TEXT_L2_X -= 45.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)) - SCREEN_SCALE_X(85)); + break; + default: + CFont::SetRightJustifyWrap(0); + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_CWL")); + CFont::SetRightJustifyWrap(0); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get("FEC_ENV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_MOV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_MOV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_CR3")); + CFont::SetRightJustifyOn(); + switch (m_PrefsLanguage) + { + case LANGUAGE_GERMAN: + TEXT_SELECT_X += 20.0f; + break; + case LANGUAGE_SPANISH: + TEXT_SELECT_X += 15.0f; + break; + default: + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + TEXT_R2_X += 30.0f; + CFont::SetJustifyOff(); + CFont::SetWrapx(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)) + SCREEN_SCALE_X(120)); + break; + default: + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_CWR")); + CFont::SetJustifyOn(); + CFont::SetWrapx(SCREEN_WIDTH); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_TAR")); + CFont::SetRightJustifyOn(); + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_JUM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_LOF")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_RUN")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_ATT")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_FPC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_LB3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get("FEC_R3")); + break; + case 3: + CFont::SetRightJustifyOn(); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + TEXT_L2_X -= 45.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)) - SCREEN_SCALE_X(85)); + break; + default: + CFont::SetRightJustifyWrap(0); + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_CWL")); + CFont::SetRightJustifyWrap(0); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get("FEC_TAR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_NA")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_MOV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_CR3")); + CFont::SetRightJustifyOn(); + switch (m_PrefsLanguage) + { + case LANGUAGE_GERMAN: + TEXT_SELECT_X += 20.0f; + break; + case LANGUAGE_SPANISH: + TEXT_SELECT_X += 15.0f; + break; + default: + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + TEXT_R2_X += 30.0f; + CFont::SetJustifyOff(); + CFont::SetWrapx(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)) + SCREEN_SCALE_X(120)); + break; + default: + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_CWR")); + CFont::SetJustifyOn(); + CFont::SetWrapx(SCREEN_WIDTH); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_ATT")); + CFont::SetRightJustifyOn(); + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_JUM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_ENV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_LOF")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_RUN")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_FPC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_LB3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get("FEC_R3")); + break; + default: + return; + } + } + else { + CFont::SetCentreOn(); + switch (m_PrefsLanguage) + { + case LANGUAGE_ITALIAN: + if (m_PrefsControllerType != CONTROLLER_XBOX360) + break; + case LANGUAGE_FRENCH: + case LANGUAGE_GERMAN: + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + break; + default: + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(0.0f)), MENU_Y(Y(TEXT_L2R2_Y)), TheText.Get("FEC_LB")); + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.9f), MENU_Y(SMALLESTTEXT_Y_SCALE* scale * 0.9f)); + switch (CPad::GetPad(0)->Mode) { + case 0: + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_LL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get("FEC_RSC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_VES")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_VES")); + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get("FEC_HO3")); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + TEXT_SELECT_X -= 5.0f; + break; + case LANGUAGE_GERMAN: + TEXT_SELECT_X += 20.0f; + break; + case LANGUAGE_SPANISH: + TEXT_SELECT_X += 15.0f; + break; + default: + break; + } + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)) - SCREEN_SCALE_X(80)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_LR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_HAB")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_EXV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_CAW")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_ACC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_TUC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_SM3")); + CFont::SetRightJustifyOn(); + switch (m_PrefsControllerType) + { + case CONTROLLER_XBOXONE: + case CONTROLLER_XBOX360: + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + TEXT_SQUARE_X += 3.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(90)); + break; + case LANGUAGE_GERMAN: + case LANGUAGE_SPANISH: + TEXT_SQUARE_X += 18.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(90)); + break; + default: + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60)); + break; + } + break; + default: + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + TEXT_SQUARE_X -= 15.0f; + TEXT_SQUARE_Y += 5.0f; + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60)); + break; + case LANGUAGE_GERMAN: + TEXT_SQUARE_X -= 15.0f; + TEXT_SQUARE_Y += 10.0f; + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE* scale * 0.65f)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60)); + break; + case LANGUAGE_SPANISH: + TEXT_SQUARE_X += 15.0f; + case LANGUAGE_ITALIAN: + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + default: + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(100)); + break; + } + break; + } + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_BRA")); + break; + case 1: + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_LL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get("FEC_HOR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_VES")); + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get("FEC_NA")); + switch (m_PrefsLanguage) + { + case LANGUAGE_GERMAN: + TEXT_SELECT_X += 20.0f; + break; + case LANGUAGE_SPANISH: + TEXT_SELECT_X += 12.0f; + break; + default: + break; + } + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)) - SCREEN_SCALE_X(80)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_RSC")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_LR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_HAB")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_EXV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_CAW")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_ACC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_TUC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_SM3")); + CFont::SetRightJustifyOn(); + switch (m_PrefsControllerType) + { + case CONTROLLER_XBOXONE: + case CONTROLLER_XBOX360: + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + TEXT_SQUARE_X += 3.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(90)); + break; + case LANGUAGE_GERMAN: + case LANGUAGE_SPANISH: + TEXT_SQUARE_X += 18.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(90)); + break; + default: + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60)); + break; + } + break; + default: + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + TEXT_SQUARE_X -= 15.0f; + TEXT_SQUARE_Y += 5.0f; + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60)); + break; + case LANGUAGE_GERMAN: + TEXT_SQUARE_X -= 15.0f; + TEXT_SQUARE_Y += 10.0f; + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60)); + break; + case LANGUAGE_SPANISH: + TEXT_SQUARE_X += 15.0f; + case LANGUAGE_ITALIAN: + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + default: + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(100)); + break; + } + break; + } + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_BRA")); + break; + case 2: + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_LL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get("FEC_EXV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_VES")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_VES")); + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get("FEC_RS3")); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + TEXT_SELECT_X -= 5.0f; + break; + case LANGUAGE_GERMAN: + TEXT_SELECT_X += 20.0f; + break; + case LANGUAGE_SPANISH: + TEXT_SELECT_X += 15.0f; + break; + default: + break; + } + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)) - SCREEN_SCALE_X(80)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_LR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_HOR")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_HAB")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_CAW")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_ACC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_TUC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_SM3")); + CFont::SetRightJustifyOn(); + switch (m_PrefsControllerType) + { + case CONTROLLER_XBOXONE: + case CONTROLLER_XBOX360: + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + TEXT_SQUARE_X += 3.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(90)); + break; + case LANGUAGE_GERMAN: + case LANGUAGE_SPANISH: + TEXT_SQUARE_X += 18.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(90)); + break; + default: + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60)); + break; + } + break; + default: + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + TEXT_SQUARE_X -= 15.0f; + TEXT_SQUARE_Y += 5.0f; + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60)); + break; + case LANGUAGE_GERMAN: + TEXT_SQUARE_X -= 15.0f; + TEXT_SQUARE_Y += 10.0f; + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60)); + break; + case LANGUAGE_SPANISH: + TEXT_SQUARE_X += 15.0f; + case LANGUAGE_ITALIAN: + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + default: + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(100)); + break; + } + break; + } + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_BRA")); + break; + case 3: + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_LL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get("FEC_HAB")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_TUC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_VES")); + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get("FEC_HO3")); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + TEXT_SELECT_X -= 5.0f; + break; + case LANGUAGE_GERMAN: + TEXT_SELECT_X += 20.0f; + break; + case LANGUAGE_SPANISH: + TEXT_SELECT_X += 15.0f; + break; + default: + break; + } + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)) - SCREEN_SCALE_X(80)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_LR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_CAW")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_EXV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_RSC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_NA")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_ACC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_BRA")); + CFont::SetRightJustifyOn(); + CFont::SetRightJustifyWrap(0); + switch (m_PrefsControllerType) + { + case CONTROLLER_XBOXONE: + case CONTROLLER_XBOX360: + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_SMT")); + break; + default: + switch (m_PrefsLanguage) + { + case LANGUAGE_GERMAN: + TEXT_SQUARE_X += 5.0f; + case LANGUAGE_FRENCH: + case LANGUAGE_ITALIAN: + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_SMT")); + break; + default: + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X + 16.0f)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_SMT")); + break; + } + break; + } + break; + default: + return; + } + } + + CFont::SetDropShadowPosition(0); // X + +#undef X +#undef Y +} + + +void +CMenuManager::LoadController(int8 type) +{ + switch (type) + { + case CONTROLLER_DUALSHOCK2: + case CONTROLLER_DUALSHOCK3: + case CONTROLLER_DUALSHOCK4: + CFont::LoadButtons("MODELS/PS3BTNS.TXD"); + break; + default: + CFont::LoadButtons("MODELS/X360BTNS.TXD"); + break; + } + + // Unload current textures + for (int i = MENUSPRITE_CONTROLLER; i <= MENUSPRITE_ARROWS4; i++) + m_aFrontEndSprites[i].Delete(); + + // Unload txd + int frontend_controller = CTxdStore::FindTxdSlot("frontend_controller"); + if (frontend_controller != -1) + CTxdStore::RemoveTxd(frontend_controller); + + // Find the new txd to load + bool bTxdMissing = true; + if (controllerTypesPaths[type]) + if (int file = CFileMgr::OpenFile(controllerTypesPaths[type])) { + CFileMgr::CloseFile(file); + bTxdMissing = false; + } + + int txdSlot = -1; + + if (bTxdMissing) + // Not found, fall back to original textures + txdSlot = CTxdStore::FindTxdSlot("frontend2"); + else { + // Found, load txd + txdSlot = frontend_controller; + if (txdSlot == -1) + txdSlot = CTxdStore::AddTxdSlot("frontend_controller"); + CTxdStore::LoadTxd(txdSlot, controllerTypesPaths[type]); + CTxdStore::AddRef(txdSlot); + } + + assert(txdSlot != -1); + // Load new textures + CTxdStore::SetCurrentTxd(txdSlot); + for (int i = MENUSPRITE_CONTROLLER; i <= MENUSPRITE_ARROWS4; i++) { + m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]); + m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); + } +} +#endif // GAMEPAD_MENU + +#undef GetBackJustUp +#undef GetBackJustDown -- cgit v1.2.3