summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/attack.h
blob: f688326dee39e3916cde03e00f92246882a65bc1 (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
#ifndef ATTACK_H
#define ATTACK_H

#include "artefact.h"
#include "itemprop-enum.h"
#include "mon-enum.h"
#include "ouch.h"

// Used throughout inheriting classes, define them here for universal access
const int HIT_WEAK   = 7;
const int HIT_MED    = 18;
const int HIT_STRONG = 36;

class attack
{
// Public Properties
public:
    // General attack properties, set on instantiation or through a normal
    // thread of execution
    actor   *attacker, *defender;
    // Who is morally responsible for the attack? Could be YOU_FAULTLESS
    // or a monster if this is a reflected ranged attack.
    actor *responsible;

    bool    attack_occurred;
    bool    cancel_attack;
    bool    did_hit;
    bool    needs_message;
    bool    attacker_visible, defender_visible;
    bool    perceived_attack, obvious_effect;


    int     to_hit;
    int     damage_done;
    int     special_damage; // TODO: We'll see if we can remove this
    int     aux_damage;     // TOOD: And this too

    int     min_delay;
    int     final_attack_delay;

    beam_type special_damage_flavour;

    bool    stab_attempt;
    int     stab_bonus;

    bool    apply_bleeding;

    int     noise_factor;

    // Fetched/Calculated from the attacker, stored to save execution time
    int             ev_margin;

    // TODO: Expand the implementation of attack_type/attack_flavour to be used
    // by players as well as monsters. It could be a good middle ground for
    // brands and attack types (presently, players don't really have an attack
    // type)
    attack_type     attk_type;
    attack_flavour  attk_flavour;
    int             attk_damage;

    item_def        *weapon;
    brand_type      damage_brand;
    skill_type      wpn_skill;

    // Attacker's shield, stored so we can reference it and determine
    // the attacker's combat effectiveness
    item_def  *shield;

    // If weapon is an artefact, its properties.
    artefact_properties_t art_props;

    // If a weapon is an unrandart, its unrandart entry.
    const unrandart_entry *unrand_entry;

    int     attacker_to_hit_penalty;

    // Attack messages
    string     attack_verb, verb_degree;
    string     no_damage_message;
    string     special_damage_message;
    string     aux_attack, aux_verb;

    // Adjusted EV penalties for defender and attacker
    int             defender_body_armour_penalty;
    int             defender_shield_penalty;
    int             attacker_body_armour_penalty;
    int             attacker_shield_penalty;
    // Combined to-hit penalty from armour and shield.
    int             attacker_armour_tohit_penalty;
    int             attacker_shield_tohit_penalty;

    item_def        *defender_shield;

    // Miscast to cause after special damage is done. If miscast_level == 0
    // the miscast is discarded if special_damage_message isn't empty.
    int    miscast_level;
    int    miscast_type;
    actor* miscast_target;

    bool      fake_chaos_attack;

    bool simu;

// Public Methods
public:
    attack(actor *attk, actor *defn, actor *blame = 0);

    // To-hit is a function of attacker/defender, defined in sub-classes
    virtual int calc_to_hit(bool random);

    // Exact copies of their melee_attack predecessors
    string actor_name(const actor *a, description_level_type desc,
                      bool actor_visible);
    string actor_pronoun(const actor *a, pronoun_type ptyp, bool actor_visible);
    string anon_name(description_level_type desc);
    string anon_pronoun(pronoun_type ptyp);

// Private Properties
    string aux_source;
    kill_method_type kill_type;

// Private Methods
protected:
    virtual void init_attack(skill_type unarmed_skill, int attack_number);

    /* Attack Phases */
    virtual bool handle_phase_attempted();
    virtual bool handle_phase_dodged() = 0;
    virtual bool handle_phase_blocked();
    virtual bool handle_phase_hit() = 0;
    virtual bool handle_phase_damaged();
    virtual bool handle_phase_killed();
    virtual bool handle_phase_end();

    /* Combat Calculations */
    virtual bool using_weapon() = 0;
    virtual int weapon_damage() = 0;
    virtual int get_weapon_plus();
    virtual int calc_base_unarmed_damage();
    int calc_stat_to_hit_base();
    int calc_stat_to_dam_base();
    virtual int calc_mon_to_hit_base() = 0;
    virtual int apply_damage_modifiers(int damage, int damage_max,
                                       bool &half_ac) = 0;
    virtual int calc_damage();
    int test_hit(int to_hit, int ev, bool randomise_ev);
    int apply_defender_ac(int damage, int damage_max = 0, bool half_ac = false);
    // Determine if we're blocking (partially or entirely)
    virtual bool attack_shield_blocked(bool verbose);
    virtual bool attack_ignores_shield(bool verbose) = 0;
    virtual bool apply_damage_brand(const char *what = NULL);
    void calc_elemental_brand_damage(beam_type flavour,
                                     int res,
                                     const char *verb,
                                     const char *what = NULL);

    /* Weapon Effects */
    virtual bool check_unrand_effects() = 0;

    /* Attack Effects */
    virtual bool mons_attack_effects() = 0;
    void alert_defender();
    bool distortion_affects_defender();
    void antimagic_affects_defender(int pow);
    void pain_affects_defender();
    void chaos_affects_defender();
    brand_type random_chaos_brand();
    void do_miscast();
    void drain_defender();

    virtual int inflict_damage(int dam, beam_type flavour = NUM_BEAMS,
                               bool clean = false);

    /* Output */
    string debug_damage_number();
    string attack_strength_punctuation(int dmg);
    string evasion_margin_adverb();

    virtual void adjust_noise() = 0;
    virtual void set_attack_verb() = 0;
    virtual void announce_hit() = 0;

    void stab_message();

    string atk_name(description_level_type desc);
    string def_name(description_level_type desc);
    string wep_name(description_level_type desc = DESC_YOUR,
                    iflags_t ignore_flags = ISFLAG_KNOW_CURSE
                                            | ISFLAG_KNOW_PLUSES);

    int modify_blood_amount(const int damage, const int dam_type);
    // TODO: Definitely want to get rid of this, which we can't really do
    // until we refactor the whole pronoun / desc usage from these lowly
    // classes all the way up to monster/player (and actor) classes.
    string defender_name(bool allow_reflexive);

    attack_flavour random_chaos_attack_flavour();

    virtual int  player_stat_modify_damage(int damage);
    virtual int  player_apply_weapon_skill(int damage);
    virtual int  player_apply_fighting_skill(int damage, bool aux);
    virtual int  player_apply_misc_modifiers(int damage);
    virtual int  player_apply_slaying_bonuses(int damage, bool aux);
    virtual int  player_apply_final_multipliers(int damage);

    virtual void player_exercise_combat_skills();

    virtual int  player_stab_tier() = 0;
    virtual int  player_stab_weapon_bonus(int damage);
    virtual int  player_stab(int damage);
    virtual void player_stab_check();
};

#endif