1 #pragma once 2 #ifndef CATA_SRC_RELIC_H 3 #define CATA_SRC_RELIC_H 4 5 #include <climits> 6 #include <cmath> 7 #include <iosfwd> 8 #include <utility> 9 #include <vector> 10 11 #include "calendar.h" 12 #include "item.h" 13 #include "magic.h" 14 #include "magic_enchantment.h" 15 #include "translations.h" 16 #include "type_id.h" 17 #include "weighted_list.h" 18 19 class Character; 20 class Creature; 21 class JsonIn; 22 class JsonObject; 23 class JsonOut; 24 class relic; 25 class relic_procgen_data; 26 struct relic_charge_info; 27 struct relic_charge_template; 28 struct tripoint; 29 30 using relic_procgen_id = string_id<relic_procgen_data>; 31 32 class relic_procgen_data 33 { 34 public: 35 36 /* 37 * various procgen values for passive enchantment values 38 * this is a template for the ability to write a little bit 39 * less code and easier maintainability for additional values 40 */ 41 template<typename T = int> 42 struct enchantment_value_passive { 43 enchant_vals::mod type; 44 // THIS CANNOT BE 0 45 int power_per_increment = 1; 46 // whatever increment is used for the point values 47 // THIS CANNOT BE 0 48 T increment = 1; 49 T min_value = 0; 50 T max_value = 0; 51 calc_powerenchantment_value_passive52 int calc_power( T level ) const { 53 return std::round( level * static_cast<float>( power_per_increment ) / 54 static_cast<float>( increment ) ); 55 } 56 57 bool was_loaded = false; 58 59 void load( const JsonObject &jo ); 60 void deserialize( JsonIn &jsin ); 61 }; 62 63 struct enchantment_active { 64 spell_id activated_spell; 65 // power cost of spell at level 0 66 int base_power = 0; 67 // power cost increment per spell level increment 68 int power_per_increment = 1; 69 // number of spell levels that give the power per increment at 70 int increment = 1; 71 // min level of the spell allowed 72 int min_level = 0; 73 // max level of the spell allowed 74 int max_level = 0; 75 calc_powerenchantment_active76 int calc_power( int level ) const { 77 return base_power + std::round( level * 78 static_cast<float>( power_per_increment ) / static_cast<float>( increment ) ); 79 } 80 81 bool was_loaded = false; 82 83 void load( const JsonObject &jo ); 84 void deserialize( JsonIn &jsin ); 85 }; 86 87 struct generation_rules { 88 // the desired power level for the generated artifact 89 int power_level = 0; 90 // the most negative (total) attributes a generated artifact can have 91 int max_negative_power = 0; 92 // the maximum number of attributes a generated artifact can have 93 int max_attributes = INT_MAX; 94 95 bool was_loaded = false; 96 void load( const JsonObject &jo ); 97 void deserialize( JsonIn &jsin ); 98 }; 99 100 enum type { 101 passive_enchantment_add, 102 passive_enchantment_mult, 103 hit_you, 104 hit_me, 105 active_enchantment, 106 last 107 }; 108 private: 109 110 weighted_int_list<relic_charge_template> charge_values; 111 weighted_int_list<enchantment_value_passive<int>> passive_add_procgen_values; 112 weighted_int_list<enchantment_value_passive<float>> passive_mult_procgen_values; 113 weighted_int_list<enchantment_active> passive_hit_you; 114 weighted_int_list<enchantment_active> passive_hit_me; 115 weighted_int_list<enchantment_active> active_procgen_values; 116 weighted_int_list<type> type_weights; 117 weighted_int_list<itype_id> item_weights; 118 119 public: 120 relic_procgen_id id; 121 122 int power_level( const enchantment &ench ) const; 123 // power level of the active spell 124 int power_level( const fake_spell &sp ) const; 125 126 item create_item( const relic_procgen_data::generation_rules &rules ) const; 127 relic generate( const generation_rules &rules, const itype_id &it_id ) const; 128 129 bool was_loaded = false; 130 131 static void load_relic_procgen_data( const JsonObject &jo, const std::string &src ); 132 void load( const JsonObject &jo, const std::string & = "" ); 133 void deserialize( JsonIn &jsin ); 134 }; 135 136 enum class relic_recharge : int { 137 none, 138 periodic, 139 solar_sunny, 140 num 141 }; 142 143 struct relic_charge_template { 144 std::pair<int, int> max_charges; 145 std::pair<int, int> init_charges; 146 std::pair<int, int> charges_per_use; 147 std::pair<time_duration, time_duration> time; 148 relic_recharge type = relic_recharge::none; 149 150 int power_level = 0; 151 152 void deserialize( JsonIn &jsin ); 153 void load( const JsonObject &jo ); 154 relic_charge_info generate() const; 155 }; 156 157 struct relic_charge_info { 158 159 bool regenerate_ammo = false; 160 int charges = 0; 161 int charges_per_use = 0; 162 int max_charges = 0; 163 relic_recharge type = relic_recharge::num; 164 165 time_duration activation_accumulator = 0_seconds; 166 time_duration activation_time = 0_seconds; 167 168 relic_charge_info() = default; 169 170 // Because multiple different charge types can overlap, cache the power 171 // level from the charge type we were generated from here to avoid confusion 172 int power = 0; 173 174 // accumulates time for charge, and increases charge if it has enough accumulated. 175 // assumes exactly one second has passed. 176 void accumulate_charge( item &parent ); 177 178 void deserialize( JsonIn &jsin ); 179 void load( const JsonObject &jo ); 180 void serialize( JsonOut &jsout ) const; 181 }; 182 183 class relic 184 { 185 private: 186 std::vector<fake_spell> active_effects; 187 std::vector<enchantment> passive_effects; 188 189 // the item's name will be replaced with this if the string is not empty 190 translation item_name_override; 191 192 relic_charge_info charge; 193 194 // activating an artifact overrides all spell casting costs 195 int moves = 0; 196 public: 197 std::string name() const; 198 // returns number of charges that should be consumed 199 int activate( Creature &caster, const tripoint &target ); 200 int charges() const; 201 int charges_per_use() const; 202 int max_charges() const; 203 204 bool has_activation() const; 205 // has a recharge type (which needs to be actively processed) 206 bool has_recharge() const; 207 208 void try_recharge( item &parent, Character *carrier, const tripoint &pos ); 209 210 void load( const JsonObject &jo ); 211 212 void serialize( JsonOut &jsout ) const; 213 void deserialize( JsonIn &jsin ); 214 215 void add_passive_effect( const enchantment &ench ); 216 void add_active_effect( const fake_spell &sp ); 217 218 std::vector<enchantment> get_enchantments() const; 219 220 int modify_value( enchant_vals::mod value_type, int value ) const; 221 void overwrite_charge( const relic_charge_info &info ); 222 223 // what is the power level of this artifact, given a specific ruleset 224 int power_level( const relic_procgen_id &ruleset ) const; 225 226 friend bool operator==( const relic &source_relic, const relic &target_relic ); 227 }; 228 229 template <typename E> struct enum_traits; 230 231 template<> 232 struct enum_traits<relic_procgen_data::type> { 233 static constexpr relic_procgen_data::type last = relic_procgen_data::type::last; 234 }; 235 236 template<> 237 struct enum_traits<relic_recharge> { 238 static constexpr relic_recharge last = relic_recharge::num; 239 }; 240 241 #endif // CATA_SRC_RELIC_H 242