Conquer Space 0.0.0
A space themed grand strategy game set in the near future, with realistic orbital mechanics, and an emphasis on economics and politics.
modifier.h
Go to the documentation of this file.
1/* Conquer Space
2 * Copyright (C) 2021-2026 Conquer Space
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17#pragma once
18
19#include <fmt/format.h>
20
21#include <numeric>
22#include <optional>
23#include <string_view>
24#include <type_traits>
25#include <utility>
26#include <vector>
27
28#include <entt/entity/entity.hpp>
29
30// Add a new target here — the enum, to-string, and from-string are all derived from this list.
31// X(EnumName, "string_key")
32#define CQSP_MODIFIER_TARGET_LIST \
33 X(ExpertiseGain, "expertise_gain") \
34 X(MaxExpertise, "max_expertise")
35
36namespace cqsp::core::components {
37enum class ModifierTarget : uint16_t {
38#define X(name, str) name,
40#undef X
41};
42
43std::string_view ModifierTargetToString(ModifierTarget t);
44std::optional<ModifierTarget> ModifierTargetFromString(std::string_view s);
45
46struct Modifier {
47 double amount;
49};
50
52
57template <ModifierOp Op = ModifierOp::Multiplicative>
59 static constexpr double identity = (Op == ModifierOp::Additive) ? 0.0 : 1.0;
60
61 double base = 0.0;
62 double sum = identity;
63 double value = 0.0;
64
65 std::vector<std::pair<entt::entity, double>> modifiers;
66
67 void recalculate() {
68 sum = std::accumulate(modifiers.begin(), modifiers.end(), identity,
69 [](double acc, const auto& m) { return acc + m.second; });
70 if constexpr (Op == ModifierOp::Additive) {
71 value = base + sum;
72 } else {
73 // Then we can't go negative with modifiers?
74 sum = std::max(sum, 0.);
75 value = base * sum;
76 }
77 }
78
79 // NOLINTNEXTLINE(google-explicit-constructor)
80 operator double() const { return value; }
81
82 ModifiableValue() = default;
83 // NOLINTNEXTLINE(google-explicit-constructor)
84 ModifiableValue(double v) : base(v), value(v) {}
85
86 template <typename T>
87 requires std::is_arithmetic_v<T>
89 base = static_cast<double>(v);
90 if constexpr (Op == ModifierOp::Additive) {
91 value = base + sum;
92 } else {
93 value = base * sum;
94 }
95 return *this;
96 }
97
98 template <typename T>
99 requires std::is_arithmetic_v<T>
101 base += static_cast<double>(v);
102 value = _combine();
103 return *this;
104 }
105 template <typename T>
106 requires std::is_arithmetic_v<T>
108 base -= static_cast<double>(v);
109 value = _combine();
110 return *this;
111 }
112 template <typename T>
113 requires std::is_arithmetic_v<T>
115 base *= static_cast<double>(v);
116 value = _combine();
117 return *this;
118 }
119 template <typename T>
120 requires std::is_arithmetic_v<T>
122 base /= static_cast<double>(v);
123 value = _combine();
124 return *this;
125 }
126
127 template <typename T>
128 requires std::is_arithmetic_v<T>
129 bool operator==(T v) const {
130 return value == static_cast<double>(v);
131 }
132 template <typename T>
133 requires std::is_arithmetic_v<T>
134 bool operator!=(T v) const {
135 return value != static_cast<double>(v);
136 }
137 template <typename T>
138 requires std::is_arithmetic_v<T>
139 bool operator<(T v) const {
140 return value < static_cast<double>(v);
141 }
142 template <typename T>
143 requires std::is_arithmetic_v<T>
144 bool operator>(T v) const {
145 return value > static_cast<double>(v);
146 }
147 template <typename T>
148 requires std::is_arithmetic_v<T>
149 bool operator<=(T v) const {
150 return value <= static_cast<double>(v);
151 }
152 template <typename T>
153 requires std::is_arithmetic_v<T>
154 bool operator>=(T v) const {
155 return value >= static_cast<double>(v);
156 }
157
158 template <typename T>
159 requires std::is_arithmetic_v<T>
160 friend double operator+(ModifiableValue lhs, T rhs) {
161 return lhs.value + static_cast<double>(rhs);
162 }
163 template <typename T>
164 requires std::is_arithmetic_v<T>
165 friend double operator+(T lhs, ModifiableValue rhs) {
166 return static_cast<double>(lhs) + rhs.value;
167 }
168 template <typename T>
169 requires std::is_arithmetic_v<T>
170 friend double operator-(ModifiableValue lhs, T rhs) {
171 return lhs.value - static_cast<double>(rhs);
172 }
173 template <typename T>
174 requires std::is_arithmetic_v<T>
175 friend double operator-(T lhs, ModifiableValue rhs) {
176 return static_cast<double>(lhs) - rhs.value;
177 }
178 template <typename T>
179 requires std::is_arithmetic_v<T>
180 friend double operator*(ModifiableValue lhs, T rhs) {
181 return lhs.value * static_cast<double>(rhs);
182 }
183 template <typename T>
184 requires std::is_arithmetic_v<T>
185 friend double operator*(T lhs, ModifiableValue rhs) {
186 return static_cast<double>(lhs) * rhs.value;
187 }
188 template <typename T>
189 requires std::is_arithmetic_v<T>
190 friend double operator/(ModifiableValue lhs, T rhs) {
191 return lhs.value / static_cast<double>(rhs);
192 }
193 template <typename T>
194 requires std::is_arithmetic_v<T>
195 friend double operator/(T lhs, ModifiableValue rhs) {
196 return static_cast<double>(lhs) / rhs.value;
197 }
198
199 private:
200 constexpr double _combine() const {
201 if constexpr (Op == ModifierOp::Additive) {
202 return base + sum;
203 } else {
204 return base * sum;
205 }
206 }
207};
208
211
212} // namespace cqsp::core::components
213
214template <cqsp::core::components::ModifierOp Op>
215struct fmt::formatter<cqsp::core::components::ModifiableValue<Op>> : fmt::formatter<double> {
216 template <typename FormatContext>
217 auto format(const cqsp::core::components::ModifiableValue<Op>& v, FormatContext& ctx) const {
218 return fmt::formatter<double>::format(static_cast<double>(v), ctx);
219 }
220};
return v
Definition: bodies.h:193
Definition: area.h:27
std::string_view ModifierTargetToString(ModifierTarget t)
Definition: modifier.cpp:21
ModifiableValue< ModifierOp::Additive > AdditiveModifier
Definition: modifier.h:209
std::optional< ModifierTarget > ModifierTargetFromString(std::string_view s)
Definition: modifier.cpp:32
ModifiableValue< ModifierOp::Multiplicative > MultiplicativeModifier
Definition: modifier.h:210
ModifierOp
Definition: modifier.h:51
ModifierTarget
Definition: modifier.h:37
Definition: clientctx.h:27
bool operator>=(T v) const
Definition: modifier.h:154
constexpr double _combine() const
Definition: modifier.h:200
friend double operator-(T lhs, ModifiableValue rhs)
Definition: modifier.h:175
friend double operator*(T lhs, ModifiableValue rhs)
Definition: modifier.h:185
double sum
Definition: modifier.h:62
bool operator!=(T v) const
Definition: modifier.h:134
ModifiableValue & operator*=(T v)
Definition: modifier.h:114
bool operator>(T v) const
Definition: modifier.h:144
ModifiableValue & operator+=(T v)
Definition: modifier.h:100
bool operator<(T v) const
Definition: modifier.h:139
static constexpr double identity
Definition: modifier.h:59
ModifiableValue(double v)
Definition: modifier.h:84
bool operator<=(T v) const
Definition: modifier.h:149
void recalculate()
Definition: modifier.h:67
double value
Definition: modifier.h:63
friend double operator-(ModifiableValue lhs, T rhs)
Definition: modifier.h:170
friend double operator+(ModifiableValue lhs, T rhs)
Definition: modifier.h:160
bool operator==(T v) const
Definition: modifier.h:129
ModifiableValue & operator-=(T v)
Definition: modifier.h:107
std::vector< std::pair< entt::entity, double > > modifiers
Definition: modifier.h:65
friend double operator/(T lhs, ModifiableValue rhs)
Definition: modifier.h:195
ModifiableValue & operator/=(T v)
Definition: modifier.h:121
double base
Definition: modifier.h:61
friend double operator*(ModifiableValue lhs, T rhs)
Definition: modifier.h:180
friend double operator+(T lhs, ModifiableValue rhs)
Definition: modifier.h:165
friend double operator/(ModifiableValue lhs, T rhs)
Definition: modifier.h:190
ModifiableValue & operator=(T v)
Definition: modifier.h:88
Definition: modifier.h:46
ModifierTarget target
Definition: modifier.h:48
double amount
Definition: modifier.h:47
auto format(const cqsp::core::components::ModifiableValue< Op > &v, FormatContext &ctx) const
Definition: modifier.h:217