diff options
Diffstat (limited to 'src/openvic-simulation/modifier/ModifierValue.cpp')
-rw-r--r-- | src/openvic-simulation/modifier/ModifierValue.cpp | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/src/openvic-simulation/modifier/ModifierValue.cpp b/src/openvic-simulation/modifier/ModifierValue.cpp new file mode 100644 index 0000000..4461048 --- /dev/null +++ b/src/openvic-simulation/modifier/ModifierValue.cpp @@ -0,0 +1,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*=(const fixed_point_t right) { + for (auto value : mutable_iterator(values)) { + value.second *= right; + } + return *this; +} + +ModifierValue ModifierValue::operator*(const fixed_point_t 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; + } +} |