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