summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/beam.h
blob: 57dd0bbe64144ac9cae9ec1cbc7c4f23512c6678 (plain) (blame)
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
/*
 *  File:       beam.h
 *  Summary:    Functions related to ranged attacks.
 *  Written by: Linley Henzell
 */


#ifndef BEAM_H
#define BEAM_H


#include "externs.h"
#include "random.h"
#include "ray.h"

class monsters;

enum demon_beam_type
{
    DMNBM_HELLFIRE,
    DMNBM_SMITING,
    DMNBM_BRAIN_FEED,
    DMNBM_MUTATION
};

enum mon_resist_type
{
    MON_RESIST,                 // monster resisted
    MON_UNAFFECTED,             // monster unaffected
    MON_AFFECTED,               // monster was affected
    MON_OTHER                   // monster unaffected, but for other reasons
};

class dist;

typedef FixedArray<int, 19, 19> explosion_map;

struct tracer_info
{
    int count;                         // # of times something "hit"
    int power;                         // total levels/hit dice affected
    int hurt;                          // # of things actually hurt
    int helped;                        // # of things actually helped
    bool dont_stop;                    // Player said not to stop on this

    tracer_info();
    void reset();

    const tracer_info &operator += (const tracer_info &other);
};

struct bolt;

typedef bool (*range_used_func)(const bolt& beam, const actor* victim,
                                int &used);
typedef bool (*beam_damage_func)(bolt& beam, actor* victim, int &dmg,
                                 std::string &dmg_msg);
typedef bool (*beam_hit_func)(bolt& beam, actor* victim, int dmg,
                              int corpse);
typedef bool (*explosion_aoe_func)(bolt& beam, const coord_def& target);

struct bolt
{
    // INPUT parameters set by caller
    spell_type  origin_spell;          // may be SPELL_NO_SPELL for non-spell
                                       // beams.
    int         range;
    unsigned    type;                  // missile gfx
    int         colour;
    beam_type   flavour;
    beam_type   real_flavour;          // for random and chaos beams this
                                       // will remain the same while flavour
                                       // changes
    bool        drop_item;             // should drop an item when done
    item_def*   item;                  // item to drop
    coord_def   source;                // beam origin
    coord_def   target;                // intended target
    dice_def    damage;
    int         ench_power, hit;
    killer_type thrower;               // what kind of thing threw this?
    int         ex_size;               // explosion radius (0==none)

    // beam_source can be -GOD_ENUM_VALUE or one of the miscast sources from
    // spl-mis.h (values are strictly greater than NON_MONSTER in that case)
    // for explosions generated by miscast effects. -cao
    int         beam_source;           // NON_MONSTER or monster index #
    std::string source_name;           // The name of the source, if it
                                       // should be different from
                                       // actor->name(), or the actor dies
                                       // prematurely.
    std::string name;
    std::string short_name;
    std::string hit_verb;              // The verb to use when this beam hits
                                       // something.  If not set, will use
                                       // "engulfs" if an explosion or cloud
                                       // and "hits" otherwise.
    int         loudness;              // Noise level on hitting or exploding.
    std::string noise_msg;             // Message to give player if the hit
                                       // or explosion isn't in view.
    bool        is_beam;               // beam? (can hit multiple targets?)
    bool        is_explosion;
    bool        is_big_cloud;          // expands into big_cloud at endpoint
    bool        aimed_at_spot;         // aimed at (x, y), should not cross
    std::string aux_source;            // source of KILL_MISC beams

    bool        affects_nothing;       // should not hit monsters or features
    bool        affects_items;         // hits items on ground/inventory

    bool        effect_known;          // did we _know_ this would happen?

    int         draw_delay;            // delay used when drawing beam.

    bolt*       special_explosion;     // For exploding with a different
                                       // flavour/damage/etc than the beam
                                       // itself.
    bool        was_missile;           // For determining if this was SPMSL_FLAME / FROST etc
                                       // this is required in order to change mulch rate on these types

    // Various callbacks.
    std::vector<range_used_func>  range_funcs;
    std::vector<beam_damage_func> damage_funcs;
    std::vector<beam_hit_func>    hit_funcs;
    std::vector<explosion_aoe_func> aoe_funcs; // Function for if the
                                               // explosion only affects
                                               // certain grid positions.

    // OUTPUT parameters (tracing, ID)
    bool        obvious_effect;        // did an 'obvious' effect happen?

    bool        seen;                  // Has player seen the beam?
    bool        heard;                 // Has the player heard the beam?

    std::vector<coord_def> path_taken; // Path beam took.

    // INTERNAL use - should not usually be set outside of beam.cc
    int         range_used;
    bool        is_tracer;       // is this a tracer?
    bool        aimed_at_feet;   // this was aimed at self!
    bool        msg_generated;   // an appropriate msg was already mpr'd
    bool        passed_target;   // Beam progressed beyond target.
    bool     in_explosion_phase; // explosion phase (as opposed to beam phase)
    bool        smart_monster;   // tracer firer can guess at other mons. resists?
    bool        can_see_invis;   // tracer firer can see invisible?
    mon_attitude_type attitude;  // attitude of whoever fired tracer
    int         foe_ratio;       // 100* foe ratio (see mons_should_fire())

    tracer_info foe_info;
    tracer_info friend_info;

    bool        chose_ray;       // do we want a specific ray?
    bool        beam_cancelled;  // stop_attack_prompt() returned true
    bool        dont_stop_player; // player answered self target prompt with 'y'

    int         bounces;         // # times beam bounced off walls
    coord_def   bounce_pos;      // position of latest wall bounce,
                                 // reset if a reflection happens

    int         reflections;     // # times beam reflected off shields
    int         reflector;       // latest thing to reflect beam

    bool        use_target_as_pos; // pos() should return ::target()
    bool        auto_hit;

    ray_def     ray;             // shoot on this specific ray

#ifdef USE_TILE
    int         tile_beam;
#endif

public:
    bolt();

    bool is_enchantment() const; // no block/dodge, use magic resist
    void set_target(const dist &targ);
    void set_agent(actor *agent);
    void setup_retrace();

    // Returns YOU_KILL or MON_KILL, depending on the source of the beam.
    killer_type  killer() const;

    kill_category whose_kill() const;

    actor* agent() const;

    void fire();

    // Returns member short_name if set, otherwise some reasonable string
    // for a short name, most likely the name of the beam's flavour.
    std::string get_short_name() const;

    // Assume that all saving throws are failed, actually apply
    // the enchantment.
    mon_resist_type apply_enchantment_to_monster(monsters* mon);

    // Return whether any affected cell was seen.
    bool explode(bool show_more = true, bool hole_in_the_middle = false);
    bool knockback_actor(actor *actor);

private:
    void do_fire();
    coord_def pos() const;

    // Lots of properties of the beam.
    bool is_blockable() const;
    bool is_superhot() const;
    bool is_fiery() const;
    bool affects_wall(dungeon_feature_type wall) const;
    bool is_bouncy(dungeon_feature_type feat) const;
    bool can_affect_wall_monster(const monsters* mon) const;
    bool stop_at_target() const;
    bool invisible() const;
    bool has_saving_throw() const;
    bool is_harmless(const monsters *mon) const;
    bool harmless_to_player() const;
    bool is_reflectable(const item_def *item) const;
    bool nasty_to(const monsters* mon) const;
    bool nice_to(const monsters* mon) const;
    bool found_player() const;
    bool need_regress() const;

    int beam_source_as_target() const;
    int range_used_on_hit(const actor* victim) const;

    std::string zapper() const;

    std::set<std::string> message_cache;
    void emit_message(msg_channel_type chan, const char* msg);
    void step();
    bool hit_wall();

    bool apply_hit_funcs(actor* victim, int dmg, int corpse = -1);
    bool apply_dmg_funcs(actor* victim, int &dmg,
                         std::vector<std::string> &messages);

    // Functions which handle actually affecting things. They all
    // operate on the beam's current position (i.e., whatever pos()
    // returns.)
public:
    void affect_cell();
    void affect_wall();
    void affect_monster( monsters* m );
    void affect_player();
    void affect_ground();
    void affect_place_clouds();
    void affect_place_explosion_clouds();
    void affect_endpoint();

    void water_hits_actor(actor *act);

    // Stuff when a monster or player is hit.
    void affect_player_enchantment();
    void tracer_affect_player();
    void tracer_affect_monster(monsters* mon);
    bool handle_statue_disintegration(monsters* mon);
    void apply_bolt_paralysis(monsters *monster);
    void apply_bolt_petrify(monsters *monster);
    void enchantment_affect_monster(monsters* mon);
    mon_resist_type try_enchant_monster(monsters *mon);
    void tracer_enchantment_affect_monster(monsters* mon);
    void tracer_nonenchantment_affect_monster(monsters* mon);
    void update_hurt_or_helped(monsters *mon);
    bool attempt_block(monsters* mon);
    void handle_stop_attack_prompt(monsters* mon);
    bool determine_damage(monsters* mon, int& preac, int& postac, int& final,
                          std::vector<std::string> &messages);
    void monster_post_hit(monsters* mon, int dmg);
    bool misses_player();

    void initialise_fire();
    void apply_beam_conducts();
    void choose_ray();
    void draw(const coord_def& p);
    void bounce();
    void reflect();
    void fake_flavour();
    void digging_wall_effect();
    void fire_wall_effect();
    void elec_wall_effect();
    void nuke_wall_effect();
    void drop_object();
    void finish_beam();
    bool fuzz_invis_tracer();

    void internal_ouch(int dam);

    // Various explosion-related stuff.
    void refine_for_explosion();
    void explosion_draw_cell(const coord_def& p);
    void explosion_affect_cell(const coord_def& p);
    void determine_affected_cells(explosion_map& m, const coord_def& delta,
                                  int count, int r,
                                  bool stop_at_statues, bool stop_at_walls);
};

int mons_adjust_flavoured(monsters *monster, bolt &pbolt, int hurted,
                          bool doFlavouredEffects = true);

// Return whether the effect was visible.
bool enchant_monster_with_flavour(monsters* mon, actor *atk,
                                  beam_type flavour, int powc = 0);

// Return true if messages were generated during the enchantment.
bool mass_enchantment( enchant_type wh_enchant, int pow, int who,
                       int *m_succumbed = NULL, int *m_attempted = NULL );

bool curare_hits_monster(actor *agent, monsters *monster, kill_category who,
                         int levels = 1);
bool poison_monster(monsters *monster, kill_category who, int levels = 1,
                    bool force = false, bool verbose = true);
bool miasma_monster(monsters *monster, kill_category who);
bool napalm_monster(monsters *monster, kill_category who, int levels = 1,
                    bool verbose = true);
void fire_tracer( const monsters *monster, struct bolt &pbolt,
                  bool explode_only = false );
void mimic_alert( monsters *mimic );
bool zapping(zap_type ztype, int power, bolt &pbolt,
             bool needs_tracer = false, const char* msg = NULL);
bool player_tracer(zap_type ztype, int power, bolt &pbolt, int range = 0);

std::string beam_type_name(beam_type type);
void clear_zap_info_on_exit();

#endif