aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/modifier/ModifierManager.hpp
blob: bb946a7e48d193cad92094bd8a10116ff2723ab4 (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
#pragma once

#include "openvic-simulation/modifier/Modifier.hpp"
#include "openvic-simulation/modifier/ModifierEffectCache.hpp"
#include "openvic-simulation/modifier/ModifierEffectMapping.hpp"
#include "openvic-simulation/modifier/StaticModifierCache.hpp"
#include "openvic-simulation/types/IdentifierRegistry.hpp"

namespace OpenVic {

   struct ModifierManager {
      friend struct StaticModifierCache;
      friend struct BuildingTypeManager;
      friend struct GoodDefinitionManager;
      friend struct UnitTypeManager;
      friend struct RebelManager;
      friend struct PopManager;
      friend struct TechnologyManager;

      using effect_variant_map_t = ordered_map<Modifier::modifier_type_t, ModifierEffect const*>;

      /* Some ModifierEffects are generated mid-load, such as max/min count modifiers for each building, so
       * we can't lock it until loading is over. This means we can't rely on locking for pointer stability,
       * so instead we store the effects in a deque which doesn't invalidate pointers on insert.
       */
   private:
      CaseInsensitiveIdentifierRegistry<ModifierEffect, RegistryStorageInfoDeque> IDENTIFIER_REGISTRY(modifier_effect);
      case_insensitive_string_set_t complex_modifiers;
      string_map_t<effect_variant_map_t> modifier_effect_variants;

      IdentifierRegistry<IconModifier> IDENTIFIER_REGISTRY(event_modifier);
      IdentifierRegistry<Modifier> IDENTIFIER_REGISTRY(static_modifier);
      IdentifierRegistry<TriggeredModifier> IDENTIFIER_REGISTRY(triggered_modifier);

      ModifierEffectCache PROPERTY(modifier_effect_cache);
      StaticModifierCache PROPERTY(static_modifier_cache);

      std::vector<ModifierEffectMapping> PROPERTY(modifier_effect_mappings);

      /* effect_validator takes in ModifierEffect const& */
      NodeTools::key_value_callback_t _modifier_effect_callback(
         ModifierValue& modifier, Modifier::modifier_type_t type, NodeTools::key_value_callback_t default_callback
      ) const;

   public:
      bool add_modifier_effect(
         ModifierEffect const*& effect_cache,
         std::string_view identifier,
         bool positive_good,
         ModifierEffect::format_t format,
         ModifierEffect::target_t targets,
         std::string_view localisation_key = {},
         // mapping_key is placed after localisation_key as it's less likely to be set explicitly
         std::string_view mapping_key = {}
      );

      bool register_complex_modifier(std::string_view identifier);
      static std::string get_flat_identifier(
         std::string_view complex_modifier_identifier, std::string_view variant_identifier
      );

      bool register_modifier_effect_variants(
         std::string const& identifier, ModifierEffect const* effect, std::vector<Modifier::modifier_type_t> const& types
      );

      bool setup_modifier_effect_mappings();
      bool setup_modifier_effects();

      bool add_event_modifier(std::string_view identifier, ModifierValue&& values, IconModifier::icon_t icon);
      bool load_event_modifiers(ast::NodeCPtr root);

      bool add_static_modifier(std::string_view identifier, ModifierValue&& values);
      bool load_static_modifiers(ast::NodeCPtr root);

      bool add_triggered_modifier(
         std::string_view identifier, ModifierValue&& values, IconModifier::icon_t icon, ConditionScript&& trigger
      );
      bool load_triggered_modifiers(ast::NodeCPtr root);

      bool parse_scripts(DefinitionManager const& definition_manager);

      NodeTools::node_callback_t expect_modifier_value_and_default(
         NodeTools::callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type,
         NodeTools::key_value_callback_t default_callback
      ) const;
      NodeTools::node_callback_t expect_modifier_value(
         NodeTools::callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type
      ) const;

      // In the functions below, key_map refers to a map from identifier strings to NodeTools::dictionary_entry_t,
      // allowing any non-modifier effect keys found to be parsed in a custom way, similar to expect_dictionary_keys.
      NodeTools::node_callback_t expect_modifier_value_and_key_map_and_default(
         NodeTools::callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type,
         NodeTools::key_value_callback_t default_callback, NodeTools::key_map_t&& key_map
      ) const;
      NodeTools::node_callback_t expect_modifier_value_and_key_map(
         NodeTools::callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type,
         NodeTools::key_map_t&& key_map
      ) const;

      template<typename... Args>
      NodeTools::node_callback_t expect_modifier_value_and_key_map_and_default(
         NodeTools::callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type,
         NodeTools::key_value_callback_t default_callback, NodeTools::key_map_t&& key_map, Args... args
      ) const {
         NodeTools::add_key_map_entries(key_map, args...);
         return expect_modifier_value_and_key_map_and_default(
            modifier_callback, type, default_callback, std::move(key_map)
         );
      }

      template<typename... Args>
      NodeTools::node_callback_t expect_modifier_value_and_keys_and_default(
         NodeTools::callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type,
         NodeTools::key_value_callback_t default_callback, Args... args
      ) const {
         return expect_modifier_value_and_key_map_and_default(modifier_callback, type, default_callback, {}, args...);
      }
      template<typename... Args>
      NodeTools::node_callback_t expect_modifier_value_and_keys(
         NodeTools::callback_t<ModifierValue&&> modifier_callback, Modifier::modifier_type_t type, Args... args
      ) const {
         return expect_modifier_value_and_key_map_and_default(
            modifier_callback, type, NodeTools::key_value_invalid_callback, {}, args...
         );
      }
   };
}