1 #pragma once
2 #ifndef CATA_SRC_MAGIC_ENCHANTMENT_H
3 #define CATA_SRC_MAGIC_ENCHANTMENT_H
4 
5 #include <iosfwd>
6 #include <map>
7 #include <new>
8 #include <set>
9 #include <utility>
10 #include <vector>
11 
12 #include "calendar.h"
13 #include "magic.h"
14 #include "optional.h"
15 #include "type_id.h"
16 #include "units_fwd.h"
17 
18 class Character;
19 class Creature;
20 class JsonObject;
21 class JsonOut;
22 class item;
23 
24 namespace enchant_vals
25 {
26 // the different types of values that can be modified by enchantments
27 // either the item directly or the Character, whichever is more appropriate
28 enum class mod : int {
29     // effects for the Character
30     STRENGTH,
31     DEXTERITY,
32     PERCEPTION,
33     INTELLIGENCE,
34     SPEED,
35     ATTACK_COST,
36     ATTACK_SPEED, // affects attack speed of item even if it's not the one you're wielding
37     MOVE_COST,
38     METABOLISM,
39     MAX_MANA,
40     REGEN_MANA,
41     BIONIC_POWER,
42     MAX_STAMINA,
43     REGEN_STAMINA,
44     MAX_HP,        // for all limbs! use with caution
45     REGEN_HP,
46     THIRST,        // thirst rate
47     FATIGUE,       // fatigue rate
48     PAIN,          // cost or regen over time
49     BONUS_DODGE,
50     BONUS_BLOCK,
51     BONUS_DAMAGE,
52     ATTACK_NOISE,
53     SHOUT_NOISE,
54     FOOTSTEP_NOISE,
55     SIGHT_RANGE,
56     CARRY_WEIGHT,
57     SOCIAL_LIE,
58     SOCIAL_PERSUADE,
59     SOCIAL_INTIMIDATE,
60     ARMOR_BASH,
61     ARMOR_CUT,
62     ARMOR_STAB,
63     ARMOR_BULLET,
64     ARMOR_HEAT,
65     ARMOR_COLD,
66     ARMOR_ELEC,
67     ARMOR_ACID,
68     ARMOR_BIO,
69     // effects for the item that has the enchantment
70     ITEM_DAMAGE_PURE,
71     ITEM_DAMAGE_BASH,
72     ITEM_DAMAGE_CUT,
73     ITEM_DAMAGE_STAB,
74     ITEM_DAMAGE_BULLET,
75     ITEM_DAMAGE_HEAT,
76     ITEM_DAMAGE_COLD,
77     ITEM_DAMAGE_ELEC,
78     ITEM_DAMAGE_ACID,
79     ITEM_DAMAGE_BIO,
80     ITEM_DAMAGE_AP,      // armor piercing
81     ITEM_ARMOR_BASH,
82     ITEM_ARMOR_CUT,
83     ITEM_ARMOR_STAB,
84     ITEM_ARMOR_BULLET,
85     ITEM_ARMOR_HEAT,
86     ITEM_ARMOR_COLD,
87     ITEM_ARMOR_ELEC,
88     ITEM_ARMOR_ACID,
89     ITEM_ARMOR_BIO,
90     ITEM_WEIGHT,
91     ITEM_ENCUMBRANCE,
92     ITEM_VOLUME,
93     ITEM_COVERAGE,
94     ITEM_ATTACK_SPEED,
95     ITEM_WET_PROTECTION,
96     NUM_MOD
97 };
98 } // namespace enchant_vals
99 
100 // an "enchantment" is what passive artifact effects used to be:
101 // under certain conditions, the effect persists upon the appropriate Character
102 class enchantment
103 {
104     public:
105         // if a Character "has" an enchantment, it is viable to check for the condition
106         enum has {
107             WIELD,
108             WORN,
109             HELD,
110             NUM_HAS
111         };
112         // the condition at which the enchantment is giving passive effects
113         enum condition {
114             ALWAYS,
115             UNDERGROUND,
116             UNDERWATER,
117             ACTIVE, // the item, mutation, etc. is active
118             NUM_CONDITION
119         };
120 
121         static void load_enchantment( const JsonObject &jo, const std::string &src );
122         void load( const JsonObject &jo, const std::string &src = "" );
123 
124         // attempts to add two like enchantments together.
125         // if their conditions don't match, return false. else true.
126         bool add( const enchantment &rhs );
127 
128         // adds two enchantments together and ignores their conditions
129         void force_add( const enchantment &rhs );
130 
131         void set_has( has value );
132 
133         void add_value_add( enchant_vals::mod value, int add_value );
134         void add_value_mult( enchant_vals::mod value, float mult_value );
135 
136         void add_hit_me( const fake_spell &sp );
137         void add_hit_you( const fake_spell &sp );
138 
139         int get_value_add( enchant_vals::mod value ) const;
140         double get_value_multiply( enchant_vals::mod value ) const;
141         // the standard way of modifying a value, adds then multiplies.
142         double modify_value( enchant_vals::mod mod_val, double value ) const;
143         units::energy modify_value( enchant_vals::mod mod_val, units::energy value ) const;
144         units::mass modify_value( enchant_vals::mod mod_val, units::mass value ) const;
145 
146         // this enchantment has a valid condition and is in the right location
147         bool is_active( const Character &guy, const item &parent ) const;
148 
149         // this enchantment has a valid item independent conditions
150         // @active means the container for the enchantment is active, for comparison to active flag.
151         bool is_active( const Character &guy, bool active ) const;
152 
153         // this enchantment is active when wielded.
154         // shows total conditional values, so only use this when Character is not available
155         bool active_wield() const;
156 
157         // modifies character stats, or does other passive effects
158         void activate_passive( Character &guy ) const;
159 
160         enchantment_id id;
161 
162         bool was_loaded = false;
163 
164         void serialize( JsonOut &jsout ) const;
165 
166         // casts all the hit_you_effects on the target
167         void cast_hit_you( Character &caster, const Creature &target ) const;
168         // casts all the hit_me_effects on self or a target depending on the enchantment definition
169         void cast_hit_me( Character &caster, const Creature *target ) const;
170 
get_mutations()171         const std::set<trait_id> &get_mutations() const {
172             return mutations;
173         }
174 
175         bool operator==( const enchantment &rhs ) const;
176     private:
177         std::set<trait_id> mutations;
178         cata::optional<emit_id> emitter;
179         std::map<efftype_id, int> ench_effects;
180         // values that add to the base value
181         std::map<enchant_vals::mod, int> values_add;
182         // values that get multiplied to the base value
183         // multipliers add to each other instead of multiply against themselves
184         std::map<enchant_vals::mod, double> values_multiply;
185 
186         std::vector<fake_spell> hit_me_effect;
187         std::vector<fake_spell> hit_you_effect;
188 
189         std::map<time_duration, std::vector<fake_spell>> intermittent_activation;
190 
191         std::pair<has, condition> active_conditions;
192 
193         void add_activation( const time_duration &dur, const fake_spell &fake );
194 
195         // checks if the enchantments have the same active_conditions
196         bool stacks_with( const enchantment &rhs ) const;
197 
198         int mult_bonus( enchant_vals::mod value_type, int base_value ) const;
199 
200         // performs cooldown and distance checks before casting enchantment spells
201         void cast_enchantment_spell( Character &caster, const Creature *target,
202                                      const fake_spell &sp ) const;
203 };
204 
205 template <typename E> struct enum_traits;
206 
207 template<>
208 struct enum_traits<enchantment::has> {
209     static constexpr enchantment::has last = enchantment::has::NUM_HAS;
210 };
211 
212 template<>
213 struct enum_traits<enchantment::condition> {
214     static constexpr enchantment::condition last = enchantment::condition::NUM_CONDITION;
215 };
216 
217 template<>
218 struct enum_traits<enchant_vals::mod> {
219     static constexpr enchant_vals::mod last = enchant_vals::mod::NUM_MOD;
220 };
221 
222 #endif // CATA_SRC_MAGIC_ENCHANTMENT_H
223