1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
#include "ModifierValue.hpp"
#include "openvic-simulation/utility/TslHelper.hpp"
using namespace OpenVic;
ModifierValue::ModifierValue() = default;
ModifierValue::ModifierValue(effect_map_t&& new_values) : values { std::move(new_values) } {}
ModifierValue::ModifierValue(ModifierValue const&) = default;
ModifierValue::ModifierValue(ModifierValue&&) = default;
ModifierValue& ModifierValue::operator=(ModifierValue const&) = default;
ModifierValue& ModifierValue::operator=(ModifierValue&&) = default;
void ModifierValue::trim() {
erase_if(values, [](effect_map_t::value_type const& value) -> bool {
return value.second == fixed_point_t::_0();
});
}
size_t ModifierValue::get_effect_count() const {
return values.size();
}
void ModifierValue::clear() {
values.clear();
}
bool ModifierValue::empty() const {
return values.empty();
}
fixed_point_t ModifierValue::get_effect(ModifierEffect const& effect, bool* effect_found) const {
const effect_map_t::const_iterator it = values.find(&effect);
if (it != values.end()) {
if (effect_found != nullptr) {
*effect_found = true;
}
return it->second;
}
if (effect_found != nullptr) {
*effect_found = false;
}
return fixed_point_t::_0();
}
fixed_point_t ModifierValue::get_effect_nullcheck(ModifierEffect const* effect, bool* effect_found) const {
if (effect != nullptr) {
return get_effect(*effect, effect_found);
}
if (effect_found != nullptr) {
*effect_found = false;
}
return fixed_point_t::_0();
}
bool ModifierValue::has_effect(ModifierEffect const& effect) const {
return values.contains(&effect);
}
void ModifierValue::set_effect(ModifierEffect const& effect, fixed_point_t value) {
values[&effect] = value;
}
ModifierValue& ModifierValue::operator+=(ModifierValue const& right) {
for (effect_map_t::value_type const& value : right.values) {
values[value.first] += value.second;
}
return *this;
}
ModifierValue ModifierValue::operator+(ModifierValue const& right) const {
ModifierValue copy = *this;
return copy += right;
}
ModifierValue ModifierValue::operator-() const {
ModifierValue copy = *this;
for (auto value : mutable_iterator(copy.values)) {
value.second = -value.second;
}
return copy;
}
ModifierValue& ModifierValue::operator-=(ModifierValue const& right) {
for (effect_map_t::value_type const& value : right.values) {
values[value.first] -= value.second;
}
return *this;
}
ModifierValue ModifierValue::operator-(ModifierValue const& right) const {
ModifierValue copy = *this;
return copy -= right;
}
ModifierValue& ModifierValue::operator*=(fixed_point_t const& right) {
for (auto value : mutable_iterator(values)) {
value.second *= right;
}
return *this;
}
ModifierValue ModifierValue::operator*(fixed_point_t const& right) const {
ModifierValue copy = *this;
return copy *= right;
}
void ModifierValue::apply_exclude_targets(ModifierEffect::target_t excluded_targets) {
using enum ModifierEffect::target_t;
// We could test if excluded_targets is NO_TARGETS (and so we do nothing) or ALL_TARGETS (and so we clear everything),
// but so long as this is always called with an explicit/hardcoded value then we'll never have either of those cases.
erase_if(
values,
[excluded_targets](effect_map_t::value_type const& value) -> bool {
return !ModifierEffect::excludes_targets(value.first->get_targets(), excluded_targets);
}
);
}
void ModifierValue::multiply_add_exclude_targets(
ModifierValue const& other, fixed_point_t multiplier, ModifierEffect::target_t excluded_targets
) {
using enum ModifierEffect::target_t;
if (multiplier == fixed_point_t::_1() && excluded_targets == NO_TARGETS) {
*this += other;
} else if (multiplier != fixed_point_t::_0()) {
// We could test that excluded_targets != ALL_TARGETS, but in practice it's always
// called with an explcit/hardcoded value and so won't ever exclude everything.
for (effect_map_t::value_type const& value : other.values) {
if (ModifierEffect::excludes_targets(value.first->get_targets(), excluded_targets)) {
values[value.first] += value.second * multiplier;
}
}
}
}
namespace OpenVic { // so the compiler shuts up
std::ostream& operator<<(std::ostream& stream, ModifierValue const& value) {
for (ModifierValue::effect_map_t::value_type const& effect : value.values) {
stream << effect.first << ": " << effect.second << "\n";
}
return stream;
}
}
|