metaforce/Runtime/CGameOptions.hpp

207 lines
7.7 KiB
C++
Raw Permalink Normal View History

2018-10-06 20:42:33 -07:00
#pragma once
2015-08-17 13:33:58 -07:00
#include <array>
#include <string_view>
#include <vector>
#include "Runtime/CWorldSaveGameInfo.hpp"
#include "Runtime/RetroTypes.hpp"
#include "Runtime/Audio/CAudioSys.hpp"
2015-08-30 20:44:42 -07:00
2021-04-10 01:42:06 -07:00
namespace metaforce {
2018-02-03 22:46:47 -08:00
struct CFinalInput;
2017-03-23 22:30:16 -07:00
class CStateManager;
2017-01-09 23:15:49 -08:00
/** Options presented in UI */
2018-12-07 21:30:43 -08:00
enum class EGameOption {
VisorOpacity,
HelmetOpacity,
HUDLag,
HintSystem,
ScreenBrightness,
ScreenOffsetX,
ScreenOffsetY,
ScreenStretch,
SFXVolume,
MusicVolume,
SoundMode,
ReverseYAxis,
Rumble,
SwapBeamControls,
RestoreDefaults
2017-01-09 23:15:49 -08:00
};
/** Option UI type */
2018-12-07 21:30:43 -08:00
enum class EOptionType { Float, DoubleEnum, TripleEnum, RestoreDefaults };
2017-01-09 23:15:49 -08:00
/** Option UI presentation information */
2018-12-07 21:30:43 -08:00
struct SGameOption {
EGameOption option;
u32 stringId;
float minVal, maxVal, increment;
EOptionType type;
2017-01-09 23:15:49 -08:00
};
/** Static registry of Option UI presentation information */
extern const std::array<std::pair<size_t, const SGameOption*>, 5> GameOptionsRegistry;
2020-04-15 23:57:04 -07:00
extern const std::array<std::pair<size_t, const SGameOption*>, 5> GameOptionsRegistryNew;
2016-09-24 18:58:20 -07:00
/** Options tracked persistently between game sessions */
2018-12-07 21:30:43 -08:00
class CPersistentOptions {
friend class CGameState;
std::array<u8, 98> x0_nesState{};
std::array<bool, 64> x68_{};
2018-12-07 21:30:43 -08:00
std::vector<std::pair<CAssetId, TEditorId>> xac_cinematicStates; /* (MLVL, Cinematic) */
u32 xbc_autoMapperKeyState = 0;
u32 xc0_frozenFpsCount = 0;
u32 xc4_frozenBallCount = 0;
u32 xc8_powerBombAmmoCount = 0;
u32 xcc_logScanPercent = 0;
bool xd0_24_fusionLinked : 1 = false;
bool xd0_25_normalModeBeat : 1 = false;
bool xd0_26_hardModeBeat : 1 = false;
bool xd0_27_fusionBeat : 1 = false;
bool xd0_28_fusionSuitActive : 1 = false;
bool xd0_29_allItemsCollected : 1 = false;
2016-09-24 18:58:20 -07:00
public:
CPersistentOptions() = default;
explicit CPersistentOptions(CInputStream& stream);
2018-12-07 21:30:43 -08:00
bool GetCinematicState(CAssetId mlvlId, TEditorId cineId) const;
void SetCinematicState(CAssetId mlvlId, TEditorId cineId, bool state);
u32 GetAutoMapperKeyState() const { return xbc_autoMapperKeyState; }
void SetAutoMapperKeyState(u32 state) { xbc_autoMapperKeyState = state; }
2018-12-07 21:30:43 -08:00
bool GetPlayerLinkedFusion() const { return xd0_24_fusionLinked; }
void SetPlayerLinkedFusion(bool fusionLinked) { xd0_24_fusionLinked = fusionLinked; }
2018-12-07 21:30:43 -08:00
bool GetPlayerBeatNormalMode() const { return xd0_25_normalModeBeat; }
void SetPlayerBeatNormalMode(bool normalModeBeat) { xd0_25_normalModeBeat = normalModeBeat; }
2018-12-07 21:30:43 -08:00
bool GetPlayerBeatHardMode() const { return xd0_26_hardModeBeat; }
void SetPlayerBeatHardMode(bool hardModeBeat) { xd0_26_hardModeBeat = hardModeBeat; }
2018-12-07 21:30:43 -08:00
bool GetPlayerBeatFusion() const { return xd0_27_fusionBeat; }
void SetPlayerBeatFusion(bool fusionBeat) { xd0_27_fusionBeat = fusionBeat; }
2018-12-07 21:30:43 -08:00
bool GetPlayerFusionSuitActive() const { return xd0_28_fusionSuitActive; }
void SetPlayerFusionSuitActive(bool fusionSuitActive) { xd0_28_fusionSuitActive = fusionSuitActive; }
2018-12-07 21:30:43 -08:00
bool GetAllItemsCollected() const { return xd0_29_allItemsCollected; }
void SetAllItemsCollected(bool allItemsCollected) { xd0_29_allItemsCollected = allItemsCollected; }
2018-12-07 21:30:43 -08:00
u32 GetLogScanPercent() const { return xcc_logScanPercent; }
void SetLogScanPercent(u32 percent) { xcc_logScanPercent = percent; }
2018-12-07 21:30:43 -08:00
void IncrementFrozenFpsCount() { xc0_frozenFpsCount = std::min(int(xc0_frozenFpsCount + 1), 3); }
bool GetShowFrozenFpsMessage() const { return xc0_frozenFpsCount != 3; }
void IncrementFrozenBallCount() { xc4_frozenBallCount = std::min(int(xc4_frozenBallCount + 1), 3); }
bool GetShowFrozenBallMessage() const { return xc4_frozenBallCount != 3; }
bool GetShowPowerBombAmmoMessage() const { return xc8_powerBombAmmoCount != 1; }
void IncrementPowerBombAmmoCount() { xc8_powerBombAmmoCount = std::min<u32>(1, xc8_powerBombAmmoCount + 1); }
void PutTo(COutputStream& w) const;
2018-12-07 21:30:43 -08:00
u8* GetNESState() { return x0_nesState.data(); }
const u8* GetNESState() const { return x0_nesState.data(); }
2016-09-24 18:58:20 -07:00
};
/** Options tracked per game session */
2018-12-07 21:30:43 -08:00
class CGameOptions {
std::array<u8, 64> x0_{};
2018-12-07 21:30:43 -08:00
CAudioSys::ESurroundModes x44_soundMode = CAudioSys::ESurroundModes::Stereo;
u32 x48_screenBrightness = 4;
s32 x4c_screenXOffset = 0;
s32 x50_screenYOffset = 0;
s32 x54_screenStretch = 0;
u32 x58_sfxVol = 0x7f;
u32 x5c_musicVol = 0x7f;
u32 x60_hudAlpha = 0xff;
u32 x64_helmetAlpha = 0xff;
bool x68_24_hudLag : 1;
bool x68_25_invertY : 1;
bool x68_26_rumble : 1;
bool x68_27_swapBeamsControls : 1;
bool x68_28_hintSystem : 1;
std::vector<std::pair<CAssetId, CAssetId>> x6c_controlTxtrMap;
2018-12-07 21:30:43 -08:00
s32 m_gamma = 0;
2016-09-24 18:58:20 -07:00
public:
2018-12-07 21:30:43 -08:00
CGameOptions();
explicit CGameOptions(CInputStream& stream);
2018-12-07 21:30:43 -08:00
void ResetToDefaults();
void InitSoundMode();
void EnsureSettings();
void PutTo(COutputStream& writer) const;
2018-12-07 21:30:43 -08:00
float TuneScreenBrightness() const;
void SetScreenBrightness(s32 value, bool apply);
2018-12-07 21:30:43 -08:00
s32 GetScreenBrightness() const { return x48_screenBrightness; }
void ApplyGamma();
void SetGamma(s32 value, bool apply);
2018-12-07 21:30:43 -08:00
s32 GetGamma() const { return m_gamma; }
void SetScreenPositionX(s32 position, bool apply);
2018-12-07 21:30:43 -08:00
s32 GetScreenPositionX() const { return x4c_screenXOffset; }
void SetScreenPositionY(s32 position, bool apply);
2018-12-07 21:30:43 -08:00
s32 GetScreenPositionY() const { return x50_screenYOffset; }
void SetScreenStretch(s32 stretch, bool apply);
2018-12-07 21:30:43 -08:00
s32 GetScreenStretch() const { return x54_screenStretch; }
void SetSfxVolume(s32 volume, bool apply);
2018-12-07 21:30:43 -08:00
s32 GetSfxVolume() const { return x58_sfxVol; }
void SetMusicVolume(s32 volume, bool apply);
2018-12-07 21:30:43 -08:00
s32 GetMusicVolume() const { return x5c_musicVol; }
void SetHUDAlpha(u32 alpha);
2018-12-07 21:30:43 -08:00
u32 GetHUDAlpha() const { return x60_hudAlpha; }
void SetHelmetAlpha(u32 alpha);
2018-12-07 21:30:43 -08:00
u32 GetHelmetAlpha() const { return x64_helmetAlpha; }
void SetHUDLag(bool lag);
2018-12-07 21:30:43 -08:00
bool GetHUDLag() const { return x68_24_hudLag; }
void SetSurroundMode(int mode, bool apply);
CAudioSys::ESurroundModes GetSurroundMode() const;
void SetInvertYAxis(bool invert);
2018-12-07 21:30:43 -08:00
bool GetInvertYAxis() const { return x68_25_invertY; }
void SetIsRumbleEnabled(bool rumble);
2018-12-07 21:30:43 -08:00
bool GetIsRumbleEnabled() const { return x68_26_rumble; }
void SetSwapBeamControls(bool swap);
2018-12-07 21:30:43 -08:00
bool GetSwapBeamControls() const { return x68_27_swapBeamsControls; }
void SetIsHintSystemEnabled(bool hints);
2018-12-07 21:30:43 -08:00
bool GetIsHintSystemEnabled() const { return x68_28_hintSystem; }
void SetControls(int controls);
void ResetControllerAssets(int controls);
const std::vector<std::pair<CAssetId, CAssetId>>& GetControlTXTRMap() const { return x6c_controlTxtrMap; }
static void TryRestoreDefaults(const CFinalInput& input, int category, int option, bool frontend, bool forceRestore);
static void SetOption(EGameOption option, int value);
static int GetOption(EGameOption option);
2016-09-24 18:58:20 -07:00
};
2018-12-07 21:30:43 -08:00
class CHintOptions {
2016-09-24 18:58:20 -07:00
public:
2018-12-07 21:30:43 -08:00
enum class EHintState { Zero, Waiting, Displaying, Delayed };
struct SHintState {
EHintState x0_state = EHintState::Zero;
float x4_time = 0.f;
bool x8_dismissed = false;
2016-09-24 18:58:20 -07:00
2018-12-07 21:30:43 -08:00
SHintState() = default;
SHintState(EHintState state, float time, bool flag) : x0_state(state), x4_time(time), x8_dismissed(flag) {}
bool CanContinue() const { return x4_time / 3.f <= 1.f; }
};
2017-02-17 18:19:50 -08:00
2016-09-24 18:58:20 -07:00
private:
2018-12-07 21:30:43 -08:00
std::vector<SHintState> x0_hintStates;
u32 x10_nextHintIdx = -1;
2016-09-24 18:58:20 -07:00
public:
2018-12-07 21:30:43 -08:00
CHintOptions() = default;
explicit CHintOptions(CInputStream& stream);
void PutTo(COutputStream& writer) const;
2018-12-07 21:30:43 -08:00
void SetNextHintTime();
void InitializeMemoryState();
const SHintState* GetCurrentDisplayedHint() const;
void DelayHint(std::string_view name);
void ActivateImmediateHintTimer(std::string_view name);
void ActivateContinueDelayHintTimer(std::string_view name);
2018-12-07 21:30:43 -08:00
void DismissDisplayedHint();
u32 GetNextHintIdx() const;
const std::vector<SHintState>& GetHintStates() const { return x0_hintStates; }
void Update(float dt, const CStateManager& stateMgr);
2015-08-17 13:33:58 -07:00
};
2021-04-10 01:42:06 -07:00
} // namespace metaforce