1 #pragma once 2 3 #include <functional> 4 #include <vector> 5 6 #include "enchant-type.h" 7 #include "mon-util.h" 8 #include "tag-version.h" 9 10 using std::vector; 11 12 #define SPECIAL_WEAPON_KEY "special_weapon_name" 13 #define CLOUD_IMMUNE_MB_KEY "cloud_immune" 14 15 enum monster_info_flags 16 { 17 MB_STABBABLE, 18 MB_DISTRACTED, 19 MB_BERSERK, 20 MB_DORMANT, 21 MB_SLEEPING, 22 MB_UNAWARE, 23 MB_WANDERING, 24 MB_HASTED, 25 MB_STRONG, 26 MB_SLOWED, 27 MB_FLEEING, 28 MB_CONFUSED, 29 MB_INVISIBLE, 30 MB_POISONED, 31 MB_MORE_POISONED, 32 MB_MAX_POISONED, 33 #if TAG_MAJOR_VERSION == 34 34 MB_ROTTING, 35 #endif 36 MB_SUMMONED, 37 MB_HALOED, 38 MB_GLOWING, 39 MB_CHARMED, 40 MB_BURNING, 41 MB_PARALYSED, 42 MB_SICK, 43 MB_CAUGHT, 44 MB_WEBBED, 45 #if TAG_MAJOR_VERSION == 34 46 MB_OLD_FRENZIED, 47 #endif 48 MB_PETRIFYING, 49 MB_PETRIFIED, 50 MB_LOWERED_WL, 51 MB_POSSESSABLE, 52 MB_ENSLAVED, 53 MB_SWIFT, 54 MB_INSANE, 55 MB_SILENCING, 56 MB_MESMERIZING, 57 #if TAG_MAJOR_VERSION == 34 58 MB_EVIL_ATTACK, 59 #endif 60 MB_SHAPESHIFTER, 61 MB_CHAOTIC, 62 MB_SUBMERGED, 63 #if TAG_MAJOR_VERSION == 34 64 MB_BLEEDING, 65 #endif 66 #if TAG_MAJOR_VERSION == 34 67 MB_PREP_RESURRECT, 68 #endif 69 MB_REGENERATION, 70 MB_STRONG_WILLED, 71 MB_MIRROR_DAMAGE, 72 MB_SAFE, 73 MB_UNSAFE, 74 MB_NAME_SUFFIX, // [art] rat foo does... 75 MB_NAME_ADJECTIVE, // [art] foo rat does... 76 MB_NAME_REPLACE, // [art] foo does 77 MB_NAME_UNQUALIFIED, // Foo does... 78 MB_NAME_THE, // The foo does.... 79 #if TAG_MAJOR_VERSION == 34 80 MB_FADING_AWAY, 81 MB_MOSTLY_FADED, 82 #endif 83 MB_FEAR_INSPIRING, 84 #if TAG_MAJOR_VERSION == 34 85 MB_WITHDRAWN, 86 MB_ATTACHED, 87 #endif 88 MB_DAZED, 89 MB_MUTE, 90 MB_BLIND, 91 MB_DUMB, 92 MB_MAD, 93 #if TAG_MAJOR_VERSION == 34 94 MB_CLINGING, 95 #endif 96 MB_NAME_ZOMBIE, 97 MB_PERM_SUMMON, 98 MB_INNER_FLAME, 99 MB_UMBRAED, 100 #if TAG_MAJOR_VERSION == 34 101 MB_OLD_ROUSED, 102 #endif 103 MB_BREATH_WEAPON, 104 #if TAG_MAJOR_VERSION == 34 105 MB_DEATHS_DOOR, 106 #endif 107 MB_FIREWOOD, 108 MB_TWO_WEAPONS, 109 MB_NO_REGEN, 110 #if TAG_MAJOR_VERSION == 34 111 MB_SUPPRESSED, 112 #endif 113 MB_ROLLING, 114 MB_RANGED_ATTACK, 115 MB_NO_NAME_TAG, 116 #if TAG_MAJOR_VERSION == 34 117 MB_MAGIC_ARMOUR, 118 #endif 119 MB_WRETCHED, 120 MB_SCREAMED, 121 MB_WORD_OF_RECALL, 122 MB_INJURY_BOND, 123 MB_WATER_HOLD, 124 MB_WATER_HOLD_DROWN, 125 MB_FLAYED, 126 #if TAG_MAJOR_VERSION == 34 127 MB_RETCHING, 128 #endif 129 MB_WEAK, 130 MB_DIMENSION_ANCHOR, 131 #if TAG_MAJOR_VERSION == 34 132 MB_CONTROL_WINDS, 133 MB_WIND_AIDED, 134 MB_SUMMONED_NO_STAIRS, // Temp. summoned and capped monsters 135 #endif 136 MB_SUMMONED_CAPPED, // Expiring due to summons cap 137 MB_TOXIC_RADIANCE, 138 MB_GRASPING_ROOTS, 139 MB_FIRE_VULN, 140 MB_VORTEX, 141 MB_VORTEX_COOLDOWN, 142 MB_BARBS, 143 MB_POISON_VULN, 144 MB_ICEMAIL, 145 MB_AGILE, 146 MB_FROZEN, 147 MB_BLACK_MARK, 148 MB_SAP_MAGIC, 149 MB_SHROUD, 150 MB_CORROSION, 151 MB_SPECTRALISED, 152 MB_SLOW_MOVEMENT, 153 MB_LIGHTLY_DRAINED, 154 MB_HEAVILY_DRAINED, 155 MB_REPEL_MSL, 156 #if TAG_MAJOR_VERSION == 34 157 MB_NEGATIVE_VULN, 158 MB_CONDENSATION_SHIELD, 159 #endif 160 MB_RESISTANCE, 161 MB_HEXED, 162 #if TAG_MAJOR_VERSION == 34 163 MB_BONE_ARMOUR, 164 MB_CHANT_FIRE_STORM, 165 MB_CHANT_WORD_OF_ENTROPY, 166 #endif 167 MB_AIRBORNE, 168 MB_BRILLIANCE_AURA, 169 MB_EMPOWERED_SPELLS, 170 MB_READY_TO_HOWL, 171 MB_PARTIALLY_CHARGED, 172 MB_FULLY_CHARGED, 173 MB_GOZAG_INCITED, 174 MB_PAIN_BOND, 175 MB_IDEALISED, 176 MB_BOUND_SOUL, 177 MB_INFESTATION, 178 MB_NO_REWARD, 179 MB_STILL_WINDS, 180 MB_SLOWLY_DYING, 181 #if TAG_MAJOR_VERSION == 34 182 MB_PINNED, 183 #endif 184 MB_VILE_CLUTCH, 185 MB_WATERLOGGED, 186 MB_CLOUD_RING_THUNDER, 187 MB_CLOUD_RING_FLAMES, 188 MB_CLOUD_RING_CHAOS, 189 MB_CLOUD_RING_MUTATION, 190 MB_CLOUD_RING_FOG, 191 MB_CLOUD_RING_ICE, 192 MB_CLOUD_RING_DRAINING, 193 MB_CLOUD_RING_ACID, 194 MB_CLOUD_RING_MIASMA, 195 MB_WITHERING, 196 MB_CRUMBLING, 197 MB_ALLY_TARGET, 198 MB_CANT_DRAIN, 199 MB_CONCENTRATE_VENOM, 200 NUM_MB_FLAGS 201 }; 202 203 struct monster_info_base 204 { 205 coord_def pos; 206 FixedBitVector<NUM_MB_FLAGS> mb; 207 string mname; 208 monster_type type; 209 monster_type base_type; 210 union 211 { 212 // These must all be the same size! 213 unsigned number; ///< General purpose number variable 214 int num_heads; ///< # of hydra heads 215 int slime_size; ///< # of slimes in this one 216 int is_active; ///< Whether this ballisto is active or not 217 }; 218 int _colour; 219 mon_attitude_type attitude; 220 mon_threat_level_type threat; 221 mon_dam_level_type dam; 222 // TODO: maybe we should store the position instead 223 dungeon_feature_type fire_blocker; 224 string description; 225 string quote; 226 mon_holy_type holi; 227 mon_intel_type mintel; 228 int hd; 229 int ac; 230 int ev; 231 int base_ev; 232 int mr; 233 resists_t mresists; 234 bool can_see_invis; 235 mon_itemuse_type mitemuse; 236 int mbase_speed; 237 mon_energy_usage menergy; 238 CrawlHashTable props; 239 string constrictor_name; 240 vector<string> constricting_name; 241 monster_spells spells; 242 mon_attack_def attack[MAX_NUM_ATTACKS]; 243 bool can_go_frenzy; 244 bool can_feel_fear; 245 246 uint32_t client_id; 247 }; 248 249 // Monster info used by the pane; precomputes some data 250 // to help with sorting and rendering. 251 struct monster_info : public monster_info_base 252 { 253 static bool less_than(const monster_info& m1, 254 const monster_info& m2, bool zombified = true, 255 bool fullname = true); 256 257 static bool less_than_wrapper(const monster_info& m1, 258 const monster_info& m2); 259 260 #define MILEV_ALL 0 261 #define MILEV_SKIP_SAFE -1 262 #define MILEV_NAME -2 monster_infomonster_info263 monster_info() { client_id = 0; } 264 explicit monster_info(const monster* m, int level = MILEV_ALL); 265 explicit monster_info(monster_type p_type, 266 monster_type p_base_type = MONS_NO_MONSTER); 267 monster_infomonster_info268 monster_info(const monster_info& mi) 269 : monster_info_base(mi), i_ghost(mi.i_ghost) 270 { 271 for (unsigned i = 0; i <= MSLOT_LAST_VISIBLE_SLOT; ++i) 272 { 273 if (mi.inv[i]) 274 inv[i].reset(new item_def(*mi.inv[i])); 275 } 276 } 277 278 monster_info& operator=(const monster_info& p) 279 { 280 if (this != &p) 281 { 282 this->~monster_info(); 283 new (this) monster_info(p); 284 } 285 return *this; 286 } 287 288 void to_string(int count, string& desc, int& desc_colour, 289 bool fullname = true, const char *adjective = nullptr, 290 bool verbose = true) const; 291 292 /* only real equipment is visible, miscellany is for mimic items */ 293 unique_ptr<item_def> inv[MSLOT_LAST_VISIBLE_SLOT + 1]; 294 295 struct 296 { 297 species_type species; 298 job_type job; 299 god_type religion; 300 skill_type best_skill; 301 short best_skill_rank; 302 short xl_rank; 303 short damage; 304 short ac; 305 } i_ghost; 306 ismonster_info307 inline bool is(unsigned mbflag) const 308 { 309 return mb[mbflag]; 310 } 311 damage_descmonster_info312 inline string damage_desc() const 313 { 314 return get_damage_level_string(holi, dam); 315 } 316 string get_max_hp_desc() const; 317 neutralmonster_info318 inline bool neutral() const 319 { 320 return attitude == ATT_NEUTRAL || attitude == ATT_GOOD_NEUTRAL || attitude == ATT_STRICT_NEUTRAL; 321 } 322 323 string db_name() const; 324 bool has_proper_name() const; 325 string pluralised_name(bool fullname = true) const; 326 string common_name(description_level_type desc = DESC_PLAIN) const; 327 string proper_name(description_level_type desc = DESC_PLAIN) const; 328 string full_name(description_level_type desc = DESC_PLAIN) const; 329 330 vector<string> attributes() const; 331 332 const char *pronoun(pronoun_type variant) const; 333 bool pronoun_plurality() const; 334 335 string wounds_description_sentence() const; 336 string wounds_description(bool colour = false) const; 337 338 string constriction_description() const; 339 340 monster_type draco_or_demonspawn_subspecies() const; 341 intelmonster_info342 mon_intel_type intel() const 343 { 344 return mintel; 345 } 346 resistsmonster_info347 resists_t resists() const 348 { 349 return mresists; 350 } 351 itemusemonster_info352 mon_itemuse_type itemuse() const 353 { 354 return mitemuse; 355 } 356 357 int randarts(artefact_prop_type ra_prop) const; 358 bool can_see_invisible() const; 359 bool nightvision() const; 360 int willpower() const; 361 int lighting_modifiers() const; 362 base_speedmonster_info363 int base_speed() const 364 { 365 return mbase_speed; 366 } 367 368 string speed_description() const; 369 370 bool wields_two_weapons() const; 371 bool can_regenerate() const; 372 reach_type reach_range() const; 373 374 size_type body_size() const; 375 376 // These should be kept in sync with the actor equivalents 377 // (Maybe unify somehow?) 378 bool cannot_move() const; 379 bool airborne() const; 380 bool ground_level() const; 381 is_namedmonster_info382 bool is_named() const 383 { 384 return !mname.empty() || mons_is_unique(type); 385 } 386 is_actual_spellcastermonster_info387 bool is_actual_spellcaster() const 388 { 389 return props.exists("actual_spellcaster"); 390 } 391 is_priestmonster_info392 bool is_priest() const 393 { 394 return props.exists("priest"); 395 } 396 397 bool has_spells() const; 398 int spell_hd(spell_type spell = SPELL_NO_SPELL) const; 399 unsigned colour(bool base_colour = false) const; 400 void set_colour(int colour); 401 402 bool has_trivial_ench(enchant_type ench) const; 403 bool debuffable() const; 404 405 protected: 406 string _core_name() const; 407 string _base_name() const; 408 string _apply_adjusted_description(description_level_type desc, const string& s) const; 409 }; 410 411 // Colour should be between -1 and 15 inclusive! 412 bool set_monster_list_colour(string key, int colour); 413 void clear_monster_list_colours(); 414 415 void get_monster_info(vector<monster_info>& mons); 416 417 void mons_to_string_pane(string& desc, int& desc_colour, bool fullname, 418 const vector<monster_info>& mi, int start, 419 int count); 420 void mons_conditions_string(string& desc, const vector<monster_info>& mi, 421 int start, int count, bool equipment); 422