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
|
#pragma once
#ifndef MONSTER_H
#define MONSTER_H
#include <bitset>
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "calendar.h"
#include "creature.h"
#include "enums.h"
#include "int_id.h"
class JsonObject;
class JsonIn;
class JsonOut;
class map;
class game;
class item;
class monfaction;
class player;
class Character;
struct mtype;
enum monster_trigger : int;
enum field_id : int;
using mfaction_id = int_id<monfaction>;
using mtype_id = string_id<mtype>;
class monster;
typedef std::map< mfaction_id, std::set< monster * > > mfactions;
class mon_special_attack
{
public:
int cooldown = 0;
bool enabled = true;
void serialize( JsonOut &jsout ) 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,
MATT_ZLAVE,
NUM_MONSTER_ATTITUDES
};
enum monster_effect_cache_fields {
MOVEMENT_IMPAIRED = 0,
FLEEING,
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();
monster( const mtype_id &id );
monster( const mtype_id &id, const tripoint &pos );
monster( const monster & ) ;
monster( monster && );
~monster() override;
monster &operator=( const monster & );
monster &operator=( monster && );
bool is_monster() const override {
return true;
}
void poly( const mtype_id &id );
bool can_upgrade();
void hasten_upgrade();
void try_upgrade( bool pin_time );
void try_reproduce();
void try_biosignature();
void spawn( const tripoint &p );
m_size get_size() const override;
units::mass get_weight() const;
units::volume get_volume() const;
int get_hp( hp_part ) const override;
int get_hp() const override;
int get_hp_max( hp_part ) const override;
int get_hp_max() const override;
int hp_percentage() const override;
// 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 ) 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;
// 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::string extended_description() const override;
// Inverts color if inv==true
bool has_flag( const m_flag f ) const override; // Returns true if f is set (see mtype.h)
bool can_see() const; // MF_SEES and no ME_BLIND
bool can_hear() const; // MF_HEARS and no ME_DEAF
bool can_submerge() const; // MF_AQUATIC or MF_SWIMS or MF_NO_BREATH, and not MF_ELECTRONIC
bool can_drown() const; // MF_AQUATIC or MF_SWIMS or MF_NO_BREATHE or MF_FLIES
bool digging() const override; // MF_DIGS or MF_CAN_DIG and diggable terrain
// Returns false if the monster is stunned, has 0 moves or otherwise wouldn't act this turn
bool can_act() const;
int sight_range( int 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 avoid_trap( const tripoint &pos, const trap &tr ) const override;
void serialize( JsonOut &jsout ) const;
void deserialize( JsonIn &jsin );
tripoint move_target(); // Returns point at the end of the monster's current plans
Creature *attack_target(); // Returns the creature at the end of plans (if hostile)
// Movement
void shift( int sx, int sy ); // Shifts the monster to the appropriate submap
// Updates current pos AND our plans
bool wander(); // Returns true if we have no plans
/**
* 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.
*/
bool can_move_to( const tripoint &p ) const;
bool will_reach( int x, int y ); // Do we have plans to get to (x, y)?
int turns_to_reach( int x, int y ); // How long will it take?
// Go in a straight line to p
void set_dest( const tripoint &p );
// Reset our plans, we've become aimless.
void unset_dest();
/**
* 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 &p, int f ); // Try to get to (x, y), we don't know
// the route. Give up after f steps.
// How good of a target is given creature (checks for visibility)
float rate_target( Creature &c, float best, bool smart = false ) const;
// Pass all factions to mon, so that hordes of same-faction mons
// do not iterate over each other
void plan( const mfactions &factions );
void move(); // Actual movement
void footsteps( const tripoint &p ); // noise made by movement
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_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 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, 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();
int bash_estimate();
/** 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_from( const tripoint &p ) override;
// Combat
bool is_fleeing( player &u ) const; // True if we're fleeing
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
void process_trigger( monster_trigger trig, int amount ); // Single trigger
int trigger_sum( const std::set<monster_trigger> &triggers ) const;
bool is_underwater() const override;
bool is_on_ground() const override;
bool is_warm() const override;
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 ) const override;
void absorb_hit( body_part bp, damage_instance &dam ) override;
bool block_hit( Creature *source, body_part &bp_hit, damage_instance &d ) override;
void melee_attack( Creature &p );
void melee_attack( Creature &p, float accuracy );
void melee_attack( Creature &p, bool ) = delete;
void deal_projectile_attack( Creature *source, dealt_projectile_attack &attack,
bool print_messages = true ) override;
void deal_damage_handle_type( const damage_unit &du, body_part bp, int &damage,
int &pain ) override;
void apply_damage( Creature *source, body_part bp, int amount,
const 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 );
/**
* 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 hp_delta, 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;
/** 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;
/** Performs any monster-specific modifications to the arguments before passing to Creature::add_effect(). */
void add_effect( const efftype_id &eff_id, time_duration dur, body_part bp = num_bp,
bool permanent = false,
int intensity = 0, bool force = false, bool deferred = false ) 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_armor_cut( body_part bp ) const override; // Natural armor, plus any worn armor
int get_armor_bash( body_part bp ) const override; // Natural armor, plus any worn armor
int get_armor_type( damage_type dt, body_part 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() override; // For the purposes of comparing to player::hit_roll()
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 ) override;
// Something hit us (possibly null source)
void on_hit( Creature *source, body_part bp_hit = num_bp,
float difficulty = INT_MIN, dealt_projectile_attack const *const proj = nullptr ) override;
// Get torso - monsters don't have body parts (yet?)
body_part get_random_body_part( bool main ) const override;
/** Returns vector containing all body parts this monster has. That is, { bp_torso } */
std::vector<body_part> get_all_body_parts( bool only_main = false ) const 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 );
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_mon
void drop_items_on_death();
// Other
/**
* Makes this monster into a fungus version
* Returns false if no such monster exists
*/
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 );
/**
* Makes monster react to heard sound
*
* @param from Location of the sound source
* @param source_volume Volume at the center of the sound source
* @param distance Distance to sound source (currently just rl_dist)
*/
void hear_sound( const tripoint &from, int source_volume, int distance );
bool is_hallucination() const override; // true if the monster isn't actually real
field_id bloodType() const override;
field_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( game_message_type type, 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( game_message_type type, const std::string &player_msg,
const std::string &npc_msg ) const override;
// TEMP VALUES
tripoint wander_pos; // Wander destination - Just try to move in that direction
int wandf; // Urge to wander - Increased by sound, decrements each move
std::vector<item> inv; // Inventory
// DEFINING VALUES
int friendly;
int anger = 0;
int morale = 0;
mfaction_id faction; // Our faction (species, for most monsters)
int mission_id; // If we're related to a mission
const mtype *type;
bool no_extra_death_drops; // if true, don't spawn loot items as part of death
bool no_corpse_quiet = false; //if true, monster dies quietly and leaves no corpse
bool death_drops =
true; // Turned to false for simulating monsters during distant missions so they don't drop in sight
bool is_dead() const;
bool made_footstep;
std::string unique_name; // If we're unique
bool hallucination;
void setpos( const tripoint &p ) override;
const tripoint &pos() const override;
inline int posx() const override {
return position.x;
}
inline int posy() const override {
return position.y;
}
inline int posz() const override {
return position.z;
}
short ignoring;
cata::optional<time_point> lastseen_turn;
// Stair data.
int staircount;
// Ammunition if we use a gun.
std::map<std::string, 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( const item &itm );
time_point last_updated = calendar::time_of_cataclysm;
int last_baby;
int last_biosig;
/**
* Do some cleanup and caching as monster is being unloaded from map.
*/
void on_unload();
/**
* Retroactively update monster.
*/
void on_load();
const pathfinding_settings &get_pathfinding_settings() const override;
std::set<tripoint> get_path_avoid() const override;
private:
int hp;
std::map<std::string, mon_special_attack> special_attacks;
tripoint goal;
tripoint position;
bool dead;
/** Legacy loading logic for monsters that are packing ammo. **/
void normalize_ammo( const int old_ammo );
/** Normal upgrades **/
int next_upgrade_time();
bool upgrades;
int upgrade_time;
bool reproduces;
int baby_timer;
bool biosignatures;
int biosig_timer;
monster_horde_attraction horde_attraction;
/** Found path. Note: Not used by monsters that don't pathfind! **/
std::vector<tripoint> path;
std::bitset<NUM_MEFF> effect_cache;
protected:
void store( JsonOut &jsout ) const;
void load( JsonObject &jsin );
/** Processes monster-specific effects of an effect. */
void process_one_effect( effect &e, bool is_new ) override;
};
#endif
|