1 /** 2 * @file 3 * @brief Functions related to ranged attacks. 4 **/ 5 6 #pragma once 7 8 #include <vector> 9 10 #include "ac-type.h" 11 #include "beam-type.h" 12 #include "enchant-type.h" 13 #include "externs.h" 14 #include "killer-type.h" 15 #include "mon-attitude-type.h" 16 #include "random.h" 17 #include "ray.h" 18 #include "spl-cast.h" 19 #include "zap-type.h" 20 21 using std::vector; 22 23 #define BEAM_STOP 1000 // all beams stopped by subtracting this 24 // from remaining range 25 26 class monster; 27 28 enum mon_resist_type 29 { 30 MON_RESIST, // monster resisted 31 MON_UNAFFECTED, // monster unaffected 32 MON_AFFECTED, // monster was affected 33 MON_OTHER, // monster unaffected, but for other reasons 34 }; 35 36 class dist; 37 38 typedef FixedArray<int, 19, 19> explosion_map; 39 40 struct tracer_info 41 { 42 int count; // # of times something "hit" 43 int power; // total levels/hit dice affected 44 int hurt; // # of things actually hurt 45 int helped; // # of things actually helped 46 bool dont_stop; // Player said not to stop on this 47 48 tracer_info(); 49 void reset(); 50 51 const tracer_info &operator += (const tracer_info &other); 52 }; 53 54 struct bolt 55 { 56 bolt(); 57 58 // INPUT parameters set by caller 59 spell_type origin_spell = SPELL_NO_SPELL; // may remain SPELL_NO_SPELL for 60 // non-spell beams. 61 int range = -2; 62 char32_t glyph = '*'; // missile gfx 63 colour_t colour = BLACK; 64 beam_type flavour = BEAM_MAGIC; 65 beam_type real_flavour = BEAM_MAGIC; // for random and chaos beams this 66 // will remain the same while flavour 67 // changes 68 bool drop_item = false; // should drop an item when done 69 item_def* item = nullptr; // item to drop 70 coord_def source = {0,0}; // beam origin 71 coord_def target = {0,0}; // intended target 72 dice_def damage = dice_def(0,0); 73 int ench_power = 0, hit = 0; 74 killer_type thrower = KILL_MISC; // what kind of thing threw this? 75 int ex_size = 0; // explosion radius (0==none) 76 77 mid_t source_id = MID_NOBODY;// The mid of the source (remains 78 // MID_NOBODY if not coming from a player 79 // or a monster). 80 string source_name = ""; // The name of the source, should it 81 // be different from agent->name(), 82 // or if the actor dies prematurely. 83 string name = ""; 84 string short_name = ""; 85 string hit_verb = ""; // The verb to use when this beam hits 86 // something. If not set, will use 87 // "engulfs" if an explosion or cloud 88 // and "hits" otherwise. 89 int loudness = 0; // Noise level on hitting or exploding. 90 string hit_noise_msg = ""; // Message to give player for each hit 91 // monster that isn't in view. 92 string explode_noise_msg = ""; // Message to give player if the explosion 93 // isn't in view. 94 bool pierce = false; // Can the beam pass through a target and 95 // hit another target behind the first? 96 bool is_explosion = false; 97 bool is_death_effect = false; // effect of e.g. ballistomycete spore 98 bool aimed_at_spot = false; // aimed at (x, y), should not cross 99 string aux_source = ""; // source of KILL_MISC beams 100 101 bool affects_nothing = false; // should not hit monsters or features 102 103 bool effect_known = true; // did we _know_ this would happen? 104 bool effect_wanton = false; // could we have guessed it would happen? 105 106 int draw_delay = 15; // delay used when drawing beam. 107 int explode_delay = 50; // delay when drawing explosions. 108 bool redraw_per_cell = true; // whether to force a redraw after every cell 109 // drawn during an animation. Not for 110 // explosions. 111 // TODO: why can't this behavior follow 112 // from draw_delay == 0? 113 114 bolt* special_explosion = nullptr; // For exploding with a different 115 // flavour/damage/etc than the beam 116 // itself. 117 bool was_missile = false; // For determining if this was SPMSL_FLAME / 118 // FROST etc so that we can change mulch rate 119 // Do we draw animations? 120 bool animate; 121 ac_type ac_rule = ac_type::normal; // How defender's AC affects damage. 122 #ifdef DEBUG_DIAGNOSTICS 123 bool quiet_debug = false; // Disable any debug spam. 124 #endif 125 126 // OUTPUT parameters (tracing, ID) 127 bool obvious_effect = false; // is this a non-enchantment, or did it already 128 // show some effect or message? (Otherwise, we'll 129 // print the canned 'nothing happened.) 130 131 bool seen = false; // Has player seen the beam? 132 bool heard = false; // Has the player heard the beam? 133 134 vector<coord_def> path_taken = {}; // Path beam took. 135 136 // INTERNAL use - should not usually be set outside of beam.cc 137 int extra_range_used = 0; 138 bool is_tracer = false; // is this a tracer? 139 bool is_targeting = false; // . . . in particular, a targeting tracer? 140 bool aimed_at_feet = false; // this was aimed at self! 141 bool msg_generated = false; // an appropriate msg was already mpr'd 142 bool noise_generated = false; // a noise has already been generated at this pos 143 bool passed_target = false; // Beam progressed beyond target. 144 bool in_explosion_phase = false; // explosion phase (as opposed to beam phase) 145 mon_attitude_type attitude = ATT_HOSTILE; // attitude of whoever fired tracer 146 int foe_ratio = 0; // 100* foe ratio (see mons_should_fire()) 147 map<mid_t, int> hit_count; // how many times targets were affected 148 149 tracer_info foe_info; 150 tracer_info friend_info; 151 152 bool chose_ray = false; // do we want a specific ray? 153 bool beam_cancelled = false; // stop_attack_prompt() returned true 154 bool dont_stop_player = false; // player answered self target prompt with 'y' 155 bool dont_stop_trees = false; // player answered tree-burning prompt with 'y' 156 157 int bounces = 0; // # times beam bounced off walls 158 coord_def bounce_pos = {0,0}; // position of latest wall bounce, 159 // reset if a reflection happens 160 161 int reflections = 0; // # times beam reflected off shields 162 mid_t reflector = MID_NOBODY; // latest thing to reflect beam 163 164 bool use_target_as_pos = false; // pos() should return ::target() 165 bool auto_hit = false; 166 167 ray_def ray; // shoot on this specific ray 168 169 int tile_beam; // only used if USE_TILE is defined 170 171 private: 172 bool can_see_invis = false; 173 bool nightvision = false; 174 175 public: 176 bool is_enchantment() const; // no block/dodge, use willpower 177 void set_target(const dist &targ); 178 void set_agent(const actor *agent); 179 void setup_retrace(); 180 181 // Returns YOU_KILL or MON_KILL, depending on the source of the beam. 182 killer_type killer() const; 183 184 kill_category whose_kill() const; 185 186 actor* agent(bool ignore_reflections = false) const; 187 188 void fire(); 189 190 // Returns member short_name if set, otherwise some reasonable string 191 // for a short name, most likely the name of the beam's flavour. 192 string get_short_name() const; 193 string get_source_name() const; 194 195 bool visible() const; 196 197 bool can_affect_actor(const actor *act) const; 198 bool can_affect_wall(const coord_def& p, bool map_knowledge = false) const; 199 bool ignores_monster(const monster* mon) const; 200 bool ignores_player() const; 201 bool can_knockback(const actor &act, int dam = -1) const; 202 bool can_pull(const actor &act, int dam = -1) const; 203 bool god_cares() const; // Will the god be unforgiving about this beam? 204 bool is_harmless(const monster* mon) const; 205 bool nasty_to(const monster* mon) const; 206 bool nice_to(const monster_info& mi) const; 207 bool has_saving_throw() const; 208 209 void draw(const coord_def& p, bool force_refresh=true); 210 void drop_object(bool allow_mulch=true); 211 212 // Various explosion-related stuff. 213 bool explode(bool show_more = true, bool hole_in_the_middle = false); 214 void refine_for_explosion(); 215 bool explosion_draw_cell(const coord_def& p); 216 void explosion_affect_cell(const coord_def& p); 217 void determine_affected_cells(explosion_map& m, const coord_def& delta, 218 int count, int r, 219 bool stop_at_statues, bool stop_at_walls); 220 221 // Setup. 222 void fake_flavour(); 223 private: 224 void do_fire(); 225 void initialise_fire(); 226 227 // Lots of properties of the beam. 228 coord_def pos() const; 229 coord_def leg_source() const; 230 cloud_type get_cloud_type() const; 231 int get_cloud_pow() const; 232 int get_cloud_size(bool min = false, bool max = false) const; 233 bool is_blockable() const; 234 bool is_omnireflectable() const; 235 bool is_fiery() const; 236 bool can_burn_trees() const; 237 bool is_bouncy(dungeon_feature_type feat) const; 238 bool stop_at_target() const; 239 bool harmless_to_player() const; 240 bool is_reflectable(const actor &whom) const; 241 bool found_player() const; 242 bool need_regress() const; 243 bool is_big_cloud() const; // expands into big_cloud at endpoint 244 int range_used_on_hit() const; 245 bool bush_immune(const monster &mons) const; 246 int apply_lighting(int base_hit, const actor &target) const; 247 248 set<string> message_cache; 249 void emit_message(const char* msg); 250 251 int apply_AC(const actor* victim, int hurted); 252 bool determine_damage(monster* mon, int& preac, int& postac, int& final); 253 254 // Functions which handle actually affecting things. They all 255 // operate on the beam's current position (i.e., whatever pos() 256 // returns.) 257 void step(); 258 public: 259 void affect_cell(); 260 void affect_endpoint(); 261 private: 262 void affect_wall(); 263 void digging_wall_effect(); 264 void growth_wall_effect(); 265 void burn_wall_effect(); 266 void affect_ground(); 267 void affect_place_clouds(); 268 void affect_place_explosion_clouds(); 269 int range_used(bool leg_only = false) const; 270 void finish_beam(); 271 272 // These methods make the beam affect a specific actor, not 273 // necessarily what's at pos(). 274 public: 275 void affect_actor(actor *act); 276 private: 277 // for monsters 278 void affect_monster(monster* m); 279 void handle_stop_attack_prompt(monster* mon); 280 bool attempt_block(monster* mon); 281 void update_hurt_or_helped(monster* mon); 282 void enchantment_affect_monster(monster* mon); 283 public: 284 mon_resist_type try_enchant_monster(monster* mon, int &res_margin); 285 mon_resist_type apply_enchantment_to_monster(monster* mon); 286 void apply_beam_conducts(); 287 private: 288 void apply_bolt_paralysis(monster* mons); 289 void apply_bolt_petrify(monster* mons); 290 void monster_post_hit(monster* mon, int dmg); 291 // for players 292 void affect_player(); 293 bool misses_player(); 294 public: 295 void affect_player_enchantment(bool resistible = true); 296 private: 297 void internal_ouch(int dam); 298 // for both 299 void knockback_actor(actor *act, int dam); 300 void pull_actor(actor *act, int dam); 301 302 // tracers 303 void tracer_affect_player(); 304 void tracer_affect_monster(monster* mon); 305 void tracer_enchantment_affect_monster(monster* mon); 306 void tracer_nonenchantment_affect_monster(monster* mon); 307 308 // methods to change the path 309 void bounce(); 310 void reflect(); 311 bool fuzz_invis_tracer(); 312 public: 313 void choose_ray(); 314 }; 315 316 int mons_adjust_flavoured(monster* mons, bolt &pbolt, int hurted, 317 bool doFlavouredEffects = true); 318 319 // Return whether the effect was visible. 320 bool enchant_actor_with_flavour(actor* victim, const actor *atk, 321 beam_type flavour, int powc = 0); 322 323 bool enchant_monster_invisible(monster* mon, const string &how); 324 325 bool ench_flavour_affects_monster(beam_type flavour, const monster* mon, 326 bool intrinsic_only = false); 327 spret mass_enchantment(enchant_type wh_enchant, int pow, 328 bool fail = false); 329 int ench_power_stepdown(int pow); 330 331 bool poison_monster(monster* mons, const actor* who, int levels = 1, 332 bool force = false, bool verbose = true); 333 bool miasma_monster(monster* mons, const actor* who); 334 bool napalm_monster(monster* mons, const actor* who, int levels = 1, 335 bool verbose = true); 336 bool curare_actor(actor* source, actor* target, int levels, string name, 337 string source_name); 338 int silver_damages_victim(actor* victim, int damage, string &dmg_msg); 339 void fire_tracer(const monster* mons, bolt &pbolt, 340 bool explode_only = false, bool explosion_hole = false); 341 spret zapping(zap_type ztype, int power, bolt &pbolt, 342 bool needs_tracer = false, const char* msg = nullptr, 343 bool fail = false); 344 bool player_tracer(zap_type ztype, int power, bolt &pbolt, int range = 0); 345 346 vector<coord_def> create_feat_splash(coord_def center, int radius, int num, int dur); 347 348 void init_zap_index(); 349 void clear_zap_info_on_exit(); 350 351 int zap_power_cap(zap_type ztype); 352 bool zap_explodes(zap_type ztype); 353 bool zap_is_enchantment(zap_type ztype); 354 int zap_ench_power(zap_type z_type, int pow, bool is_monster); 355 int zap_to_hit(zap_type z_type, int power, bool is_monster); 356 dice_def zap_damage(zap_type z_type, int power, bool is_monster, bool random = true); 357 colour_t zap_colour(zap_type z_type); 358 359 void zappy(zap_type z_type, int power, bool is_monster, bolt &pbolt); 360 void bolt_parent_init(const bolt &parent, bolt &child); 361 362 int explosion_noise(int rad); 363 364 bool always_shoot_through_monster(const actor *agent, const monster &mon); 365 bool shoot_through_monster(const bolt& beam, const monster* victim); 366 367 int omnireflect_chance_denom(int SH); 368 369 void glaciate_freeze(monster* mon, killer_type englaciator, 370 int kindex); 371 372 bolt setup_targetting_beam(const monster &mons); 373