-
Notifications
You must be signed in to change notification settings - Fork 4.2k
/
monster.h
684 lines (595 loc) · 28.6 KB
/
monster.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
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
#pragma once
#ifndef CATA_SRC_MONSTER_H
#define CATA_SRC_MONSTER_H
#include <bitset>
#include <climits>
#include <cstddef>
#include <functional>
#include <iosfwd>
#include <map>
#include <new>
#include <optional>
#include <set>
#include <utility>
#include <vector>
#include "calendar.h"
#include "character_id.h"
#include "color.h"
#include "compatibility.h"
#include "creature.h"
#include "damage.h"
#include "enums.h"
#include "point.h"
#include "type_id.h"
#include "units_fwd.h"
#include "value_ptr.h"
#include "weakpoint.h"
class Character;
class JsonObject;
class JsonOut;
class effect;
class effect_source;
class item;
struct monster_plan;
namespace catacurses
{
class window;
} // namespace catacurses
struct dealt_projectile_attack;
struct pathfinding_settings;
struct trap;
enum class mon_trigger : int;
class mon_special_attack
{
public:
int cooldown = 0;
bool enabled = true;
void serialize( JsonOut &json ) const;
// deserialize inline in monster::load due to backwards/forwards compatibility concerns
};
enum monster_attitude {
MATT_NULL = 0,
MATT_FRIEND,
MATT_FPASSIVE,
MATT_FLEE,
MATT_IGNORE,
MATT_FOLLOW,
MATT_ATTACK,
NUM_MONSTER_ATTITUDES
};
enum monster_effect_cache_fields {
MOVEMENT_IMPAIRED = 0,
FLEEING,
VISION_IMPAIRED,
NUM_MEFF
};
enum monster_horde_attraction {
MHA_NULL = 0,
MHA_ALWAYS,
MHA_LARGE,
MHA_OUTDOORS,
MHA_OUTDOORS_AND_LARGE,
MHA_NEVER,
NUM_MONSTER_HORDE_ATTRACTION
};
class monster : public Creature
{
friend class editmap;
public:
monster();
explicit monster( const mtype_id &id );
monster( const mtype_id &id, const tripoint &pos );
monster( const monster & );
monster( monster && ) noexcept( map_is_noexcept );
~monster() override;
monster &operator=( const monster & );
monster &operator=( monster && ) noexcept( string_is_noexcept );
bool is_monster() const override {
return true;
}
monster *as_monster() override {
return this;
}
const monster *as_monster() const override {
return this;
}
mfaction_id get_monster_faction() const override {
return faction.id();
}
void poly( const mtype_id &id );
bool can_upgrade() const;
void hasten_upgrade();
int get_upgrade_time() const;
void allow_upgrade();
void try_upgrade( bool pin_time );
void set_baby_timer( const time_point &time );
void try_reproduce();
void try_biosignature();
void refill_udders();
void digest_food();
void spawn( const tripoint &p );
void spawn( const tripoint_abs_ms &loc );
std::vector<material_id> get_absorb_material() const;
std::vector<material_id> get_no_absorb_material() const;
creature_size get_size() const override;
units::mass get_weight() const override;
units::mass weight_capacity() const override;
units::volume get_volume() const;
int get_hp( const bodypart_id & ) const override;
int get_hp() const override;
int get_hp_max( const bodypart_id & ) const override;
int get_hp_max() const override;
int hp_percentage() const override;
int get_eff_per() const override;
void witness_thievery( item *it ) override;
float get_mountable_weight_ratio() const;
static std::string speed_description( float mon_speed_rating,
bool immobile = false,
const speed_description_id &speed_desc = speed_description_id::NULL_ID() );
// Access
std::string get_name() const override;
std::string name( unsigned int quantity = 1 ) const; // Returns the monster's formal name
std::string name_with_armor() const; // Name, with whatever our armor is called
// the creature-class versions of the above
std::string disp_name( bool possessive = false, bool capitalize_first = false ) const override;
std::string skin_name() const override;
void get_HP_Bar( nc_color &color, std::string &text ) const;
std::pair<std::string, nc_color> get_attitude() const;
int print_info( const catacurses::window &w, int vStart, int vLines, int column ) const override;
void print_info_imgui() const;
// Information on how our symbol should appear
nc_color basic_symbol_color() const override;
nc_color symbol_color() const override;
const std::string &symbol() const override;
bool is_symbol_highlighted() const override;
nc_color color_with_effects() const; // Color with fire, beartrapped, etc.
std::vector<std::string> extended_description() const override;
// Inverts color if inv==true
// // Returns true if f is set (see mtype.h)
bool has_flag( const mon_flag_id &f ) const final;
// Evaluates monster for both JSON and monster flags (converted to mon_flag_id)
bool has_flag( flag_id f ) const;
bool can_see() const; // MF_SEES and no MF_BLIND
bool can_hear() const; // MF_HEARS and no MF_DEAF
bool can_submerge() const; // MF_AQUATIC or swims() or MF_NO_BREATH, and not MF_ELECTRONIC
bool can_drown() const; // MF_AQUATIC or swims() or MF_NO_BREATHE or flies()
bool can_climb() const; // climbs() or flies()
bool digging() const override; // digs() or can_dig() and diggable terrain
bool can_dig() const;
bool digs() const;
bool flies() const;
bool climbs() const;
bool swims() const;
// Returns false if the monster is stunned, has 0 moves or otherwise wouldn't act this turn
bool can_act() const;
int sight_range( float light_level ) const override;
bool made_of( const material_id &m ) const override; // Returns true if it's made of m
bool made_of_any( const std::set<material_id> &ms ) const override;
bool made_of( phase_id p ) const; // Returns true if its phase is p
bool shearable() const;
bool is_pet() const;
bool is_pet_follow() const;
bool has_intelligence() const;
bool avoid_trap( const tripoint &pos, const trap &tr ) const override;
void serialize( JsonOut &json ) const;
void deserialize( const JsonObject &data );
void deserialize( const JsonObject &data, const tripoint_abs_sm &submap_loc );
// Performs any necessary coordinate updates due to map shift.
void shift( const point &sm_shift );
void set_patrol_route( const std::vector<point> &patrol_pts_rel_ms );
/**
* Checks whether we can move to/through p. This does not account for bashing.
*
* This is used in pathfinding and ONLY checks the terrain. It ignores players
* and monsters, which might only block this tile temporarily.
* will_move_to() checks for impassable terrain etc
* can_reach_to() checks for z-level difference.
* can_move_to() is a wrapper for both of them.
* know_danger_at() checks for fire, trap etc. (flag PATH_AVOID_)
*/
// TODO: Get rid of untyped overload
bool can_move_to( const tripoint &p ) const;
bool can_move_to( const tripoint_bub_ms &p ) const;
bool can_reach_to( const tripoint &p ) const;
bool will_move_to( const tripoint &p ) const;
bool know_danger_at( const tripoint &p ) const;
bool will_reach( const point &p ); // Do we have plans to get to (x, y)?
int turns_to_reach( const point &p ); // How long will it take?
// Returns true if the monster has a current goal
bool has_dest() const;
// Returns point at the end of the monster's current plans
tripoint_abs_ms get_dest() const;
// Returns the creature at the end of plans (if hostile)
Creature *attack_target();
// Go towards p using the monster's pathfinding settings.
void set_dest( const tripoint_abs_ms &p );
// Reset our plans, we've become aimless.
void unset_dest();
// Returns true if the monster has no plans.
bool is_wandering() const;
/**
* Set p as wander destination.
*
* This will cause the monster to slowly move towards the destination,
* unless there is an overriding smell or plan.
*
* @param p Destination of monster's wanderings
* @param f The priority of the destination, as well as how long we should
* wander towards there.
*/
void wander_to( const tripoint_abs_ms &p, int f );
// How good of a target is given creature (checks for visibility)
float rate_target( Creature &c, float best, bool smart = false ) const;
// is it mating season?
bool mating_angry() const;
void plan();
void anger_hostile_seen( const monster_plan &mon_plan );
void anger_mating_season( const monster_plan &mon_plan );
// will change mon_plan::dist
void anger_cub_threatened( monster_plan &mon_plan );
void move(); // Actual movement
void footsteps( const tripoint &p ); // noise made by movement
void shove_vehicle( const tripoint &remote_destination,
const tripoint &nearby_destination ); // shove vehicles out of the way
// check if the given square could drown a drownable monster
bool is_aquatic_danger( const tripoint &at_pos ) const;
// check if a monster at a position will drown and kill it if necessary
// returns true if the monster dies
// chance is the one_in( chance ) that the monster will drown
bool die_if_drowning( const tripoint &at_pos, int chance = 1 );
tripoint scent_move();
int calc_movecost( const tripoint &f, const tripoint &t ) const;
int calc_climb_cost( const tripoint &f, const tripoint &t ) const;
bool is_immune_field( const field_type_id &fid ) const override;
/**
* Attempt to move to p.
*
* If there's something blocking the movement, such as infinite move
* costs at the target, an existing NPC or monster, this function simply
* aborts and does nothing.
*
* @param p Destination of movement
* @param force If this is set to true, the movement will happen even if
* there's currently something, else than a creature, blocking the destination.
* @param step_on_critter If this is set to true, the movement will happen even if
* there's currently a creature blocking the destination.
*
* @param stagger_adjustment is a multiplier for move cost to compensate for staggering.
*
* @return true if movement successful, false otherwise
*/
bool move_to( const tripoint &p, bool force = false, bool step_on_critter = false,
float stagger_adjustment = 1.0 );
/**
* Attack any enemies at the given location.
*
* Attacks only if there is a creature at the given location towards
* we are hostile.
*
* @return true if something was attacked, false otherwise
*/
bool attack_at( const tripoint &p );
/**
* Try to smash/bash/destroy your way through the terrain at p.
*
* @return true if we destroyed something, false otherwise.
*/
bool bash_at( const tripoint &p );
/**
* Try to push away whatever occupies p, then step in.
* May recurse and try to make the creature at p push further.
*
* @param p Location of pushed object
* @param boost A bonus on the roll to represent a horde pushing from behind
* @param depth Number of recursions so far
*
* @return True if we managed to push something and took its place, false otherwise.
*/
bool push_to( const tripoint &p, int boost, size_t depth );
/** Returns innate monster bash skill, without calculating additional from helpers */
int bash_skill() const;
int bash_estimate() const;
/** Returns ability of monster and any cooperative helpers to
* bash the designated target. **/
int group_bash_skill( const tripoint &target );
void stumble();
void knock_back_to( const tripoint &to ) override;
// Combat
bool is_fleeing( Character &u ) const;
monster_attitude attitude( const Character *u = nullptr ) const; // See the enum above
Attitude attitude_to( const Creature &other ) const override;
void process_triggers(); // Process things that anger/scare us
bool is_underwater() const override;
bool is_on_ground() const override;
bool is_warm() const override;
bool in_species( const species_id &spec ) const override;
void respond_to_light( float light_level );
bool has_weapon() const override;
bool is_dead_state() const override; // check if we should be dead or not
bool is_elec_immune() const override;
bool is_immune_effect( const efftype_id & ) const override;
bool is_immune_damage( const damage_type_id & ) const override;
void make_bleed( const effect_source &source, time_duration duration,
int intensity = 1, bool permanent = false, bool force = false, bool defferred = false );
const weakpoint *absorb_hit( const weakpoint_attack &attack, const bodypart_id &bp,
damage_instance &dam ) override;
// The monster's skill in hitting a weakpoint
float weakpoint_skill() const;
bool block_hit( Creature *source, bodypart_id &bp_hit, damage_instance &d ) override;
bool melee_attack( Creature &target );
bool melee_attack( Creature &target, float accuracy );
void melee_attack( Creature &p, bool ) = delete;
void deal_projectile_attack( Creature *source, dealt_projectile_attack &attack,
bool print_messages = true,
const weakpoint_attack &wp_attack = weakpoint_attack() ) override;
void deal_damage_handle_type( const effect_source &source, const damage_unit &du, bodypart_id bp,
int &damage, int &pain ) override;
void apply_damage( Creature *source, bodypart_id bp, int dam,
bool bypass_med = false ) override;
// create gibs/meat chunks/blood etc all over the place, does not kill, can be called on a dead monster.
void explode();
// Let the monster die and let its body explode into gibs
void die_in_explosion( Creature *source );
void heal_bp( bodypart_id bp, int dam ) override;
/**
* Flat addition to the monsters @ref hp. If `overheal` is true, this is not capped by max hp.
* Returns actually healed hp.
*/
int heal( int delta_hp, bool overheal = false );
/**
* Directly set the current @ref hp of the monster (not capped at the maximal hp).
* You might want to use @ref heal / @ref apply_damage or @ref deal_damage instead.
*/
void set_hp( int hp );
/** Processes monster-specific effects before calling Creature::process_effects(). */
void process_effects() override;
/** Returns true if the monster has its movement impaired */
bool movement_impaired();
/** Processes effects which may prevent the monster from moving (bear traps, crushed, etc.).
* Returns false if movement is stopped. */
bool move_effects( bool attacking ) override;
/** Returns a std::string containing effects for descriptions */
std::string get_effect_status() const;
float power_rating() const override;
float speed_rating() const override;
int get_worn_armor_val( const damage_type_id &dt ) const;
int get_armor_type( const damage_type_id &dt, bodypart_id bp ) const override;
float get_hit_base() const override;
float get_dodge_base() const override;
float get_dodge() const override; // Natural dodge, or 0 if we're occupied
float get_melee() const override; // For determining attack skill when awarding dodge practice.
float hit_roll() const override; // For the purposes of comparing to player::dodge_roll()
float dodge_roll() const override; // For the purposes of comparing to player::hit_roll()
bool can_attack_high() const override; // Can we attack upper limbs?
int get_grab_strength() const; // intensity of grabbed effect
void add_grab( bodypart_str_id bp );
void remove_grab( bodypart_str_id bp );
bool is_grabbing( bodypart_str_id bp );
monster_horde_attraction get_horde_attraction();
void set_horde_attraction( monster_horde_attraction mha );
bool will_join_horde( int size );
/** Returns multiplier on fall damage at low velocity (knockback/pit/1 z-level, not 5 z-levels) */
float fall_damage_mod() const override;
/** Deals falling/collision damage with terrain/creature at pos */
int impact( int force, const tripoint &pos ) override;
bool has_grab_break_tec() const override;
float stability_roll() const override;
// We just dodged an attack from something
void on_dodge( Creature *source, float difficulty, float training_level = 0.0 ) override;
void on_try_dodge() override {}
// Something hit us (possibly null source)
void on_hit( Creature *source, bodypart_id bp_hit,
float difficulty = INT_MIN, dealt_projectile_attack const *proj = nullptr ) override;
/** Resets a given special to its monster type cooldown value */
void reset_special( const std::string &special_name );
/** Resets a given special to a value between 0 and its monster type cooldown value. */
void reset_special_rng( const std::string &special_name );
/** Sets a given special to the given value */
void set_special( const std::string &special_name, int time );
/** Sets the enabled flag for the given special to false */
void disable_special( const std::string &special_name );
/** Test whether the monster has the specified special regardless of readiness. */
bool has_special( const std::string &special_name ) const;
/** Test whether the specified special is ready. */
bool special_available( std::string_view special_name ) const;
void process_turn() override;
/** Resets the value of all bonus fields to 0, clears special effect flags. */
void reset_bonuses() override;
/** Resets stats, and applies effects in an idempotent manner */
void reset_stats() override;
void die( Creature *killer ) override; //this is the die from Creature, it calls kill_mo
void drop_items_on_death( item *corpse );
void spawn_dissectables_on_death( item *corpse ) const; //spawn dissectable CBMs into CORPSE pocket
//spawn monster's inventory without killing it
void generate_inventory( bool disableDrops = true );
// Other
/**
* Makes this monster into a fungus version
* Returns false if no such monster exists
* Returns true if monster is immune or if it got fungalized
*/
bool make_fungus();
void make_friendly();
/** Makes this monster an ally of the given monster. */
void make_ally( const monster &z );
// Add an item to inventory
void add_item( const item &it );
/**
* Consume UPS from mech battery.
* @param amt amount of energy to consume. Is rounded down to kJ precision. Do not use negative values.
* @return Actual amount of energy consumed
*/
units::energy use_mech_power( units::energy amt );
bool check_mech_powered() const;
int mech_str_addition() const;
/**
* Makes monster react to heard sound
*
* @param source Location of the sound source
* @param vol Volume at the center of the sound source
* @param distance Distance to sound source (currently just rl_dist)
*/
void hear_sound( const tripoint &source, int vol, int distance, bool provocative );
bool is_hallucination() const override; // true if the monster isn't actually real
bool is_electrical() const override; // true if the monster produces electric radiation
bool is_fae() const override; // true if the monster is a faerie creature
bool is_nether() const override; // true if the monster is from the nether
bool has_mind() const override; // true if the monster is sapient and capable of reason
field_type_id bloodType() const override;
field_type_id gibType() const override;
using Creature::add_msg_if_npc;
void add_msg_if_npc( const std::string &msg ) const override;
void add_msg_if_npc( const game_message_params ¶ms, const std::string &msg ) const override;
using Creature::add_msg_player_or_npc;
void add_msg_player_or_npc( const std::string &player_msg,
const std::string &npc_msg ) const override;
void add_msg_player_or_npc( const game_message_params ¶ms, const std::string &player_msg,
const std::string &npc_msg ) const override;
// currently grabbed limbs
std::unordered_set<bodypart_str_id> grabbed_limbs;
tripoint_abs_ms wander_pos; // Wander destination - Just try to move in that direction
bool provocative_sound = false; // Are we wandering toward something we think is alive?
int wandf = 0; // Urge to is_wandering - Increased by sound, decrements each move
std::vector<item> inv; // Inventory
std::vector<item> dissectable_inv; // spawned at death, tracked for respawn/dissection
Character *mounted_player = nullptr; // player that is mounting this creature
character_id mounted_player_id; // id of player that is mounting this creature ( for save/load )
character_id dragged_foe_id; // id of character being dragged by the monster
cata::value_ptr<item> tied_item; // item used to tie the monster
cata::value_ptr<item> tack_item; // item representing saddle and reins and such
cata::value_ptr<item> armor_item; // item of armor the monster may be wearing
cata::value_ptr<item> storage_item; // storage item for monster carrying items
cata::value_ptr<item> battery_item; // item to power mechs
units::mass get_carried_weight() const;
units::volume get_carried_volume() const;
void move_special_item_to_inv( cata::value_ptr<item> &it );
// DEFINING VALUES
int friendly = 0;
int anger = 0;
int morale = 0;
private:
int stomach_size = 0;
int amount_eaten = 0;
void recheck_fed_status();
public:
void set_amount_eaten( int new_amount );
void mod_amount_eaten( int amount_to_add );
int get_amount_eaten() const;
// Truncates to integer for ease of use
int get_stomach_fullness_percent() const;
// Whether the monster has eaten enough to reproduce/make milk/get by normally
bool has_eaten_enough() const;
// Whether their stomach is completely full or more
// TODO: Find out why can we even exceed stomach size??
bool has_fully_eaten() const;
// Our faction (species, for most monsters)
mfaction_id faction;
// If we're related to a mission
std::set<int> mission_ids;
// Names of mission monsters fused with this monster
std::vector<std::string> mission_fused;
const mtype *type;
// If true, don't spawn loot items as part of death.
bool no_extra_death_drops = false;
// If true, monster dies quietly and leaves no corpse.
bool no_corpse_quiet = false;
// Turned to false for simulating monsters during distant missions so they don't drop in sight.
bool death_drops = true;
// If true, sound and message is suppressed for monster death.
bool quiet_death = false;
bool is_dead() const;
bool made_footstep = false;
//if we are a nemesis monster from the 'hunted' trait
bool is_nemesis() const;
// If we're unique
std::string unique_name;
// Player given nickname
std::string nickname;
bool hallucination = false;
// abstract for a fish monster representing a hidden stock of population in that area.
int fish_population = 1;
short ignoring = 0;
bool aggro_character = true;
std::optional<time_point> lastseen_turn;
pimpl<enchant_cache> enchantment_cache;
// Stair data.
int staircount = 0;
// Ammunition if we use a gun.
std::map<itype_id, int> ammo;
/**
* Convert this monster into an item (see @ref mtype::revert_to_itype).
* Only useful for robots and the like, the monster must have at least
* a non-empty item id as revert_to_itype.
*/
item to_item() const;
/**
* Initialize values like speed / hp from data of an item.
* This applies to robotic monsters that are spawned by invoking an item (e.g. turret),
* and to reviving monsters that spawn from a corpse.
*/
void init_from_item( item &itm );
/**
* Do some cleanup and caching as monster is being unloaded from map.
*/
void on_unload();
/**
* Retroactively update monster.
* Call this after a preexisting monster has been placed on map.
* Don't call for monsters that have been freshly created, it may cause
* the monster to upgrade itself into another monster type.
*/
void on_load();
const pathfinding_settings &get_pathfinding_settings() const override;
std::function<bool( const tripoint & )> get_path_avoid() const override;
double calculate_by_enchantment( double modify, enchant_vals::mod value,
bool round_output = false ) const;
private:
void process_trigger( mon_trigger trig, int amount );
void process_trigger( mon_trigger trig, const std::function<int()> &amount_func );
int hp = 0;
std::map<std::string, mon_special_attack, std::less<>> special_attacks;
std::optional<tripoint_abs_ms> goal;
bool dead = false;
/** Normal upgrades **/
int next_upgrade_time();
bool upgrades = false;
int upgrade_time = 0;
bool reproduces = false;
std::optional<time_point> baby_timer;
bool biosignatures = false;
std::optional<time_point> biosig_timer;
time_point udder_timer;
time_point stomach_timer;
monster_horde_attraction horde_attraction = MHA_NULL;
/** Found path. Note: Not used by monsters that don't pathfind! **/
std::vector<tripoint> path;
// Exponential backoff for stuck monsters. Massively reduces pathfinding CPU.
time_point pathfinding_cd = calendar::turn;
time_duration pathfinding_backoff = 2_seconds;
bool can_pathfind() const {
return pathfinding_cd <= calendar::turn;
}
void reset_pathfinding_cd() {
pathfinding_cd = calendar::turn;
pathfinding_backoff = 2_seconds;
}
void increment_pathfinding_cd() {
pathfinding_cd = calendar::turn + pathfinding_backoff;
pathfinding_backoff = std::min( pathfinding_backoff * 2, 10_seconds );
}
/** patrol points for monsters that can pathfind and have a patrol route! **/
std::vector<tripoint_abs_ms> patrol_route;
int next_patrol_point = -1;
std::bitset<NUM_MEFF> effect_cache;
int turns_since_target = 0;
Character *find_dragged_foe();
void nursebot_operate( Character *dragged_foe );
protected:
void store( JsonOut &json ) const;
void load( const JsonObject &data );
void load( const JsonObject &data, const tripoint_abs_sm &submap_loc );
void on_move( const tripoint_abs_ms &old_pos ) override;
/** Processes monster-specific effects of an effect. */
void process_one_effect( effect &it, bool is_new ) override;
};
#endif // CATA_SRC_MONSTER_H