aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/modifier/ModifierValue.cpp
blob: 51d41bccc305e520b5a087097073cfdc2282db1c (plain) (blame)
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
#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_target_filter(ModifierEffect::target_t targets) {
   using enum ModifierEffect::target_t;

   erase_if(
      values,
      [targets](effect_map_t::value_type const& value) -> bool {
         return (value.first->get_targets() & targets) == NO_TARGETS;
      }
   );
}

void ModifierValue::multiply_add_filter(
   ModifierValue const& other, fixed_point_t multiplier, ModifierEffect::target_t targets
) {
   using enum ModifierEffect::target_t;

   if (multiplier == fixed_point_t::_1() && targets == ALL_TARGETS) {
      *this += other;
   } else if (multiplier != fixed_point_t::_0() && targets != NO_TARGETS) {
      for (effect_map_t::value_type const& value : other.values) {
         if ((value.first->get_targets() & targets) != NO_TARGETS) {
            values[value.first] += value.second * multiplier;
         }
      }
   }
}