forked from cataclysmbnteam/Cataclysm-BN
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mutation.h
520 lines (451 loc) · 20.2 KB
/
mutation.h
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
#pragma once
#ifndef CATA_SRC_MUTATION_H
#define CATA_SRC_MUTATION_H
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include "bodypart.h"
#include "calendar.h"
#include "creature.h"
#include "damage.h"
#include "hash_utils.h"
#include "memory_fast.h"
#include "point.h"
#include "pldata.h"
#include "translations.h"
#include "type_id.h"
#include "value_ptr.h"
class Character;
class JsonObject;
class Trait_group;
class item;
class nc_color;
template <typename E> struct enum_traits;
template <typename T> class string_id;
class JsonArray;
extern std::map<std::string, std::vector<trait_id> > mutations_category;
struct mut_attack {
/** Text printed when the attack is proced by you */
std::string attack_text_u;
/** As above, but for npc */
std::string attack_text_npc;
/** Need all of those to qualify for this attack */
std::set<trait_id> required_mutations;
/** Need none of those to qualify for this attack */
std::set<trait_id> blocker_mutations;
/** If not num_bp, this body part needs to be uncovered for the attack to proc */
body_part bp = num_bp;
/** Chance to proc is one_in( chance - dex - unarmed ) */
int chance = 0;
damage_instance base_damage;
/** Multiplied by strength and added to the above */
damage_instance strength_damage;
/** Should be true when and only when this attack needs hardcoded handling */
bool hardcoded_effect = false;
};
struct mut_transform {
trait_id target;
/** displayed if player sees transformation with %s replaced by item name */
translation msg_transform;
/** used to set the active property of the transformed @ref target */
bool active = false;
/** subtracted from @ref Creature::moves when transformation is successful */
int moves = 0;
mut_transform();
bool load( const JsonObject &jsobj, const std::string &member );
};
struct mutation_branch {
trait_id id;
bool was_loaded = false;
// True if this is a valid mutation (False for "unavailable from generic mutagen").
bool valid = false;
// True if Purifier can remove it (False for *Special* mutations).
bool purifiable = false;
// True if it's a threshold itself, and shouldn't be obtained *easily* (False by default).
bool threshold = false;
// True if this is a trait associated with professional training/experience, so profession/quest ONLY.
bool profession = false;
// True if the mutation is obtained through the debug menu
bool debug = false;
// True if the mutation should be displayed in the `@` menu
bool player_display = true;
// Whether it has positive as well as negative effects.
bool mixed_effect = false;
bool startingtrait = false;
bool activated = false;
// Should it activate as soon as it is gained?
bool starts_active = false;
// Allow soft (fabric) gear on restricted body parts
bool allow_soft_gear = false;
// IF any of the three are true, it drains that as the "cost"
bool fatigue = false;
bool hunger = false;
bool thirst = false;
// How many points it costs in character creation
int points = 0;
int visibility = 0;
int ugliness = 0;
int cost = 0;
// costs are consumed every cooldown turns,
int cooldown = 0;
// bodytemp elements:
int bodytemp_min = 0;
int bodytemp_max = 0;
int bodytemp_sleep = 0;
// Pain Recovery per turn:
float pain_recovery = 0.0f;
// Healing per turn
float healing_awake = 0.0f;
float healing_resting = 0.0f;
// Limb mending bonus
float mending_modifier = 1.0f;
// Bonus HP multiplier. That is, 1.0 doubles hp, -0.5 halves it.
float hp_modifier = 0.0f;
// Second HP modifier that stacks with first but is otherwise identical.
float hp_modifier_secondary = 0.0f;
// Flat bonus/penalty to hp.
float hp_adjustment = 0.0f;
// Modify strength stat without changing HP
float str_modifier = 0.0f;
//melee bonuses
int cut_dmg_bonus = 0;
float pierce_dmg_bonus = 0.0;
std::pair<int, int> rand_cut_bonus;
int bash_dmg_bonus = 0;
std::pair<int, int> rand_bash_bonus;
// Additional bonuses
float dodge_modifier = 0.0f;
float speed_modifier = 1.0f;
float movecost_modifier = 1.0f;
float movecost_flatground_modifier = 1.0f;
float movecost_obstacle_modifier = 1.0f;
float attackcost_modifier = 1.0f;
float max_stamina_modifier = 1.0f;
float weight_capacity_modifier = 1.0f;
float hearing_modifier = 1.0f;
float movecost_swim_modifier = 1.0f;
float noise_modifier = 1.0f;
float scent_modifier = 1.0f;
float bleed_resist = 0;
std::optional<int> scent_intensity;
std::optional<int> scent_mask;
int butchering_quality = 0;
cata::value_ptr<mut_transform> transform;
/**Map of crafting skills modifiers, can be negative*/
std::map<skill_id, int> craft_skill_bonus;
/**What do you smell like*/
std::optional<scenttype_id> scent_typeid;
/**Map of glowing body parts and their glow intensity*/
std::map<body_part, float> lumination;
/**How fast does healthy tends toward healthy_mod*/
float healthy_rate = 1.0f;
/**maximum damage dealt by water every minute when wet. Can be negative and regen hit points.*/
int weakness_to_water = 0;
// Subtracted from the range at which monsters see player, corresponding to percentage of change. Clamped to +/- 60 for effectiveness
float stealth_modifier = 0.0f;
/** Night vision range (in tiles), added to NV from stats. Only the highest value from all mutations applies. */
float night_vision_range = 0.0f;
// Speed lowers--or raises--for every X F (X C) degrees below or above 65 F (18.3 C)
float temperature_speed_modifier = 0.0f;
// Extra metabolism rate multiplier. 1.0 doubles usage, -0.5 halves.
float metabolism_modifier = 0.0f;
// As above but for thirst.
float thirst_modifier = 0.0f;
// As above but for fatigue.
float fatigue_modifier = 0.0f;
// Modifier for the rate at which fatigue and sleep deprivation drops when resting.
float fatigue_regen_modifier = 0.0f;
// Modifier for the rate at which stamina regenerates.
float stamina_regen_modifier = 0.0f;
// Adjusts sight range on the overmap. Positives make it farther, negatives make it closer.
float overmap_sight = 0.0f;
// Multiplier for sight range, defaulting to 1.
float overmap_multiplier = 1.0f;
// Multiplier for reading speed, defaulting to 1.
float reading_speed_multiplier = 1.0f;
// Multiplier for skill rust, defaulting to 1.
float skill_rust_multiplier = 1.0f;
// Bonus or penalty to social checks (additive). 50 adds 50% to success, -25 subtracts 25%
social_modifiers social_mods;
/** The item, if any, spawned by the mutation */
itype_id spawn_item;
/**Species ignoring character with the mutation*/
std::vector<species_id> ignored_by;
/**Map of angered species and there intensity*/
std::map<species_id, int> anger_relations;
/**List of material required for food to be be edible*/
std::set<material_id> can_only_eat;
/**List of healing items allowed*/
std::set<itype_id> can_only_heal_with;
std::set<itype_id> can_heal_with;
/**List of allowed mutatrion category*/
std::set<std::string> allowed_category;
/**List of body parts locked out of bionics*/
std::set<bodypart_str_id> no_cbm_on_bp;
// Body size from mutations, e.g. large, small, etc.
std::optional<m_size> body_size;
// amount of mana added or subtracted from max
float mana_modifier = 0.0f;
float mana_multiplier = 1.0f;
float mana_regen_multiplier = 1.0f;
// spells learned and their associated level when gaining the mutation
std::map<spell_id, int> spells_learned;
/** mutation enchantments */
std::vector<enchantment_id> enchantments;
private:
std::string raw_spawn_item_message;
public:
std::string spawn_item_message() const;
/** The fake gun, if any, spawned and fired by the ranged mutation */
itype_id ranged_mutation;
private:
std::string raw_ranged_mutation_message;
public:
std::string ranged_mutation_message() const;
/** Attacks granted by this mutation */
std::vector<mut_attack> attacks_granted;
/** Mutations may adjust one or more of the default vitamin usage rates */
std::map<vitamin_id, time_duration> vitamin_rates;
// Mutations may affect absorption rates of vitamins based on material (or "all")
std::map<material_id, std::map<vitamin_id, double>> vitamin_absorb_multi;
std::vector<trait_id> prereqs; // Prerequisites; Only one is required
std::vector<trait_id> prereqs2; // Prerequisites; need one from here too
std::vector<trait_id> threshreq; // Prerequisites; dedicated slot to needing thresholds
std::set<std::string> types; // Mutation types, you can't have two mutations that share a type
std::vector<trait_id> cancels; // Mutations that conflict with this one
std::vector<trait_id> replacements; // Mutations that replace this one
std::vector<trait_id> additions; // Mutations that add to this one
std::vector<std::string> category; // Mutation Categories
std::set<std::string> flags; // Mutation flags
std::map<body_part, tripoint> protection; // Mutation wet effects
std::map<body_part, int> encumbrance_always; // Mutation encumbrance that always applies
// Mutation encumbrance that applies when covered with unfitting item
std::map<body_part, int> encumbrance_covered;
// Body parts that now need OVERSIZE gear
std::set<body_part> restricts_gear;
// Mutation stat mods
/** Key pair is <active: bool, mod type: "STR"> */
std::unordered_map<std::pair<bool, std::string>, int, cata::tuple_hash> mods;
std::map<body_part, resistances> armor;
std::vector<matype_id>
initial_ma_styles; // Martial art styles that can be chosen upon character generation
private:
translation raw_name;
translation raw_desc;
public:
std::string name() const;
std::string desc() const;
/**
* Returns the color to display the mutation name with.
*/
nc_color get_display_color() const;
/**
* Returns true if a character with this mutation shouldn't be able to wear given item.
*/
bool conflicts_with_item( const item &it ) const;
/**
* Returns damage resistance on a given body part granted by this mutation.
*/
const resistances &damage_resistance( body_part bp ) const;
/**
* Shortcut for getting the name of a (translated) mutation, same as
* @code get( mutation_id ).name @endcode
*/
static std::string get_name( const trait_id &mutation_id );
/**
* All known mutations. Key is the mutation id, value is the mutation_branch that you would
* also get by calling @ref get.
*/
static const std::vector<mutation_branch> &get_all();
// For init.cpp: reset (clear) the mutation data
static void reset_all();
// For init.cpp: load mutation data from json
void load( const JsonObject &jo, const std::string &src );
static void load_trait( const JsonObject &jo, const std::string &src );
// For init.cpp: check internal consistency (valid ids etc.) of all mutations
static void check_consistency();
/**
* Load a trait blacklist specified by the given JSON object.
*/
static void load_trait_blacklist( const JsonObject &jsobj );
/**
* Check if the trait with the given ID is blacklisted.
*/
static bool trait_is_blacklisted( const trait_id &tid );
/** called after all JSON has been read and performs any necessary cleanup tasks */
static void finalize();
static void finalize_trait_blacklist();
/**
* @name Trait groups
*
* Trait groups are used to generate a randomized set of traits.
* You usually only need the @ref Trait_group::traits_from function to
* create traits from a group.
*/
/*@{*/
/**
* Callback for the init system (@ref DynamicDataLoader), loads a trait
* group definitions.
* @param jsobj The json object to load from.
* @throw JsonError if the json object contains invalid data.
*/
static void load_trait_group( const JsonObject &jsobj );
/**
* Load a trait group from json. It differs from the other load_trait_group function as it
* uses the group ID and subtype given as parameters, and does not look them up in
* the json data (i.e. the given json object does not need to have them).
*
* This is intended for inline definitions of trait groups, e.g. in NPC class definitions:
* the trait group there is embedded into the class type definition.
*
* @param jsobj The json object to load from.
* @param gid The ID of the group that is to be loaded.
* @param subtype The type of the trait group, either "collection", "distribution" or "old"
* (i.e. the old list-based format, `[ ["TRAIT", 100] ]`).
* @throw JsonError if the json object contains invalid data.
*/
static void load_trait_group( const JsonObject &jsobj, const trait_group::Trait_group_tag &gid,
const std::string &subtype );
/**
* Like the above function, except this function assumes that the given
* array is the "entries" member of the trait group.
*
* For each element in the array, @ref mutation_branch::add_entry is called.
*
* Assuming the input array looks like `[ x, y, z ]`, this function loads it like the
* above would load this object:
* \code
* {
* "subtype": "depends on is_collection parameter",
* "id": "identfier",
* "entries": [ x, y, z ]
* }
* \endcode
* Note that each entry in the array has to be a JSON object. The other function above
* can also load data from arrays of strings, where the strings are item or group ids.
*/
static void load_trait_group( const JsonArray &entries, const trait_group::Trait_group_tag &gid,
bool is_collection );
/**
* Create a new trait group as specified by the given JSON object and register
* it as part of the given trait group.
*/
static void add_entry( Trait_group &tg, const JsonObject &obj );
/**
* Get the trait group object specified by the given ID, or null if no
* such group exists.
*/
static shared_ptr_fast<Trait_group> get_group( const trait_group::Trait_group_tag &gid );
/**
* Return the idents of all trait groups that are known.
*/
static std::vector<trait_group::Trait_group_tag> get_all_group_names();
};
struct mutation_category_trait {
private:
std::string raw_name;
// Message when you consume mutagen
std::string raw_mutagen_message;
// Message when you inject an iv
std::string raw_iv_message;
std::string raw_iv_sound_message = "NULL";
std::string raw_iv_sound_id = "shout";
std::string raw_iv_sound_variant = "default";
std::string raw_iv_sleep_message = "NULL";
std::string raw_junkie_message;
// Memorial message when you cross a threshold
std::string raw_memorial_message;
public:
std::string name() const;
std::string mutagen_message() const;
std::string iv_message() const;
std::string iv_sound_message() const;
std::string iv_sound_id() const;
std::string iv_sound_variant() const;
std::string iv_sleep_message() const;
std::string junkie_message() const;
std::string memorial_message_male() const;
std::string memorial_message_female() const;
// Mutation category i.e "BIRD", "CHIMERA"
std::string id;
// The trait that you gain when you break the threshold for this category
trait_id threshold_mut;
// These are defaults
int mutagen_hunger = 10;
int mutagen_thirst = 10;
int mutagen_pain = 0;
int mutagen_fatigue = 5;
int mutagen_morale = 0;
// The minimum mutations an injection provides
int iv_min_mutations = 1;
int iv_additional_mutations = 2;
// Chance of additional mutations
int iv_additional_mutations_chance = 3;
int iv_hunger = 10;
int iv_thirst = 10;
int iv_pain = 2;
int iv_fatigue = 5;
int iv_morale = 0;
int iv_morale_max = 0;
// Determines if you make a sound when you inject mutagen
bool iv_sound = false;
// The amount of noise produced by the sound
int iv_noise = 0;
// Whether the iv has a chance of knocking you out.
bool iv_sleep = false;
int iv_sleep_dur = 0;
static const std::map<std::string, mutation_category_trait> &get_all();
static const mutation_category_trait &get_category( const std::string &category_id );
static void reset();
static void check_consistency();
static void load( const JsonObject &jsobj );
};
void load_mutation_type( const JsonObject &jsobj );
void reset_mutation_types();
bool mutation_category_is_valid( const std::string &cat );
bool mutation_type_exists( const std::string &id );
std::vector<trait_id> get_mutations_in_types( const std::set<std::string> &ids );
std::vector<trait_id> get_mutations_in_type( const std::string &id );
bool trait_display_sort( const trait_id &a, const trait_id &b ) noexcept;
bool trait_display_nocolor_sort( const trait_id &a, const trait_id &b ) noexcept;
bool are_conflicting_traits( const trait_id &trait_a, const trait_id &trait_b );
bool b_is_lower_trait_of_a( const trait_id &trait_a, const trait_id &trait_b );
bool b_is_higher_trait_of_a( const trait_id &trait_a, const trait_id &trait_b );
bool are_opposite_traits( const trait_id &trait_a, const trait_id &trait_b );
bool are_same_type_traits( const trait_id &trait_a, const trait_id &trait_b );
bool contains_trait( std::vector<string_id<mutation_branch>> traits, const trait_id &trait );
/** Check to see if the specified character has enough resources to use that mutation. */
bool can_use_mutation( const trait_id &mut, const Character &character );
/** Calls can_use_mutation and if it fails, print a standard message. */
bool can_use_mutation_warn( const trait_id &mut, const Character &character );
enum class mutagen_technique : int {
consumed_mutagen,
injected_mutagen,
consumed_purifier,
injected_purifier,
injected_smart_purifier,
num_mutagen_techniques // last
};
template<>
struct enum_traits<mutagen_technique> {
static constexpr mutagen_technique last = mutagen_technique::num_mutagen_techniques;
};
enum class mutagen_rejection {
accepted,
rejected,
destroyed
};
struct mutagen_attempt {
mutagen_attempt( bool a, int c ) : allowed( a ), charges_used( c ) {}
bool allowed;
int charges_used;
};
mutagen_attempt mutagen_common_checks( Character &guy, const item &it, bool strong,
mutagen_technique technique );
void test_crossing_threshold( Character &guy, const mutation_category_trait &m_category );
#endif // CATA_SRC_MUTATION_H