Etterna 0.74.4
Loading...
Searching...
No Matches
ModsGroup.h
1#ifndef MODS_GROUP_H
2#define MODS_GROUP_H
3
4#include "EnumHelper.h"
5#include "RageUtil/Misc/RageTimer.h"
6// ReSharper disable once CppUnusedIncludeDirective MACROS LUL
7#include "Etterna/Models/Songs/SongOptions.h"
8
9#include <cassert>
10
11enum ModsLevel
12{
13 ModsLevel_Preferred, // user-chosen player options. Does not include any
14 // forced mods.
15 ModsLevel_Stage, // Preferred + forced stage mods
16 ModsLevel_Song, // Stage + forced attack mods
17 ModsLevel_Current, // Approaches Song
18 NUM_ModsLevel,
19 ModsLevel_Invalid
20};
21LuaDeclareType(ModsLevel);
22
23#define MODS_GROUP_ASSIGN(group, level, member, val) \
24 (group).Assign((level), member, (val))
25#define MODS_GROUP_ASSIGN_N(group, level, member, n, val) \
26 (group).Assign_n((level), member, (n), (val))
27#define MODS_GROUP_CALL(group, level, fun) (group).Call((level), fun)
28
29#define PO_GROUP_ASSIGN(group, level, member, val) \
30 MODS_GROUP_ASSIGN((group), (level), &PlayerOptions::member, (val))
31#define PO_GROUP_ASSIGN_N(group, level, member, n, val) \
32 MODS_GROUP_ASSIGN_N((group), (level), &PlayerOptions::member, (n), (val))
33#define PO_GROUP_CALL(group, level, fun) \
34 MODS_GROUP_CALL((group), (level), &PlayerOptions::fun)
35#define SO_GROUP_ASSIGN(group, level, member, val) \
36 MODS_GROUP_ASSIGN((group), (level), &SongOptions::member, (val))
37#define SO_GROUP_ASSIGN_N(group, level, member, n, val) \
38 MODS_GROUP_ASSIGN_N((group), (level), &SongOptions::member, (n), (val))
39#define SO_GROUP_CALL(group, level, fun) \
40 MODS_GROUP_CALL((group), (level), &SongOptions::fun)
41
42template<class T>
44{
45 T m_[NUM_ModsLevel]{};
46 RageTimer m_Timer;
47
48 public:
49 void Init() { Call(ModsLevel_Preferred, &T::Init); }
50
51 void Update(float fDelta)
52 {
53 // Don't let the mod approach speed be affected by Tab.
54 // TODO(Sam): Find a more elegant way of handling this.
55 fDelta = m_Timer.GetDeltaTime();
56 m_[ModsLevel_Current].Approach(m_[ModsLevel_Song], fDelta);
57 }
58
59 template<typename U>
60 void Assign(ModsLevel level, U T::*member, const U& val)
61 {
62 if (level != ModsLevel_Song)
63 m_[ModsLevel_Current].*member = val;
64 for (; level < ModsLevel_Current; enum_add(level, 1))
65 m_[level].*member = val;
66 }
67
68 template<typename U, int n>
69 void Assign_n(ModsLevel level,
70 U (T::*member)[n],
71 size_t index,
72 const U& val)
73 {
74 assert(index < n);
75 if (level != ModsLevel_Song)
76 (m_[ModsLevel_Current].*member)[index] = val;
77 for (; level < ModsLevel_Current; enum_add(level, 1))
78 (m_[level].*member)[index] = val;
79 }
80
81 void Assign(ModsLevel level, const T& val)
82 {
83 if (level != ModsLevel_Song)
84 m_[ModsLevel_Current] = val;
85 for (; level < ModsLevel_Current; enum_add(level, 1))
86 m_[level] = val;
87 }
88
89 void Call(ModsLevel level, void (T::*fun)())
90 {
91 if (level != ModsLevel_Song)
92 (m_[ModsLevel_Current].*fun)();
93 for (; level < ModsLevel_Current; enum_add(level, 1))
94 (m_[level].*fun)();
95 }
96
97 void FromString(ModsLevel level, const std::string& str)
98 {
99 if (level != ModsLevel_Song)
100 m_[ModsLevel_Current].FromString(str);
101 for (; level < ModsLevel_Current; enum_add(level, 1))
102 m_[level].FromString(str);
103 }
104
105 void SetCurrentToLevel(ModsLevel level)
106 {
107 m_[ModsLevel_Current] = m_[level];
108 }
109
110 [[nodiscard]] auto Get(ModsLevel l) const -> const T& { return m_[l]; }
111 [[nodiscard]] auto GetPreferred() const -> const T&
112 {
113 return m_[ModsLevel_Preferred];
114 }
115 [[nodiscard]] auto GetStage() const -> const T&
116 {
117 return m_[ModsLevel_Stage];
118 }
119 [[nodiscard]] auto GetSong() const -> const T&
120 {
121 return m_[ModsLevel_Song];
122 }
123 [[nodiscard]] auto GetCurrent() const -> const T&
124 {
125 return m_[ModsLevel_Current];
126 }
127 auto Get(ModsLevel l) -> T& { return m_[l]; }
128 auto GetPreferred() -> T& { return m_[ModsLevel_Preferred]; }
129 auto GetStage() -> T& { return m_[ModsLevel_Stage]; }
130 auto GetSong() -> T& { return m_[ModsLevel_Song]; }
131 auto GetCurrent() -> T& { return m_[ModsLevel_Current]; }
132};
133
134#endif
Definition ModsGroup.h:44
Definition RageTimer.h:9