summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/fight.h
blob: 70427a8ec1ae2e303eb7691e3cb25ea2298c0f4c (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
/*
 *  File:       fight.h
 *  Summary:    Functions used during combat.
 *  Written by: Linley Henzell
 */


#ifndef FIGHT_H
#define FIGHT_H


#include "externs.h"
#include "artefact.h"
#include "mon-util.h"

enum unarmed_attack_type
{
    UNAT_NO_ATTACK,                    //    0
    UNAT_KICK,
    UNAT_HEADBUTT,
    UNAT_TAILSLAP,
    UNAT_PUNCH,
    UNAT_BITE
};

enum unchivalric_attack_type
{
    UCAT_NO_ATTACK,                    //    0
    UCAT_DISTRACTED,
    UCAT_CONFUSED,
    UCAT_FLEEING,
    UCAT_INVISIBLE,
    UCAT_HELD_IN_NET,
    UCAT_PETRIFYING,
    UCAT_PETRIFIED,
    UCAT_PARALYSED,
    UCAT_SLEEPING
};

enum attack_final_effect_flavor
{
    FINEFF_LIGHTNING_DISCHARGE
};
struct attack_final_effect
{
    attack_final_effect_flavor flavor;
    coord_def location;
};

struct mon_attack_def;

int effective_stat_bonus( int wepType = -1 );

int resist_adjust_damage(actor *defender, beam_type flavour,
                         int res, int rawdamage, bool ranged = false);

int weapon_str_weight( object_class_type wpn_class, int wpn_type );
bool you_attack(int monster_attacked, bool unarmed_attacks);
bool monster_attack_actor(monsters *attacker, actor *defender,
                          bool allow_unarmed);
bool monster_attack(monsters* attacker, bool allow_unarmed = true);
bool monsters_fight(monsters* attacker, monsters* attacked,
                    bool allow_unarmed = true);

bool wielded_weapon_check(item_def *weapon, bool no_message = false);
int calc_your_to_hit(bool random_factor);
int calc_heavy_armour_penalty(bool random_factor);

unchivalric_attack_type is_unchivalric_attack(const actor *attacker,
                                              const actor *defender);

class melee_attack
{
public:
    actor     *attacker, *defender;

    monsters* attacker_as_monster()
    {
        return dynamic_cast<monsters*>(attacker);
    }

    monsters* defender_as_monster()
    {
        return dynamic_cast<monsters*>(defender);
    }

    bool      cancel_attack;
    bool      did_hit, perceived_attack, obvious_effect;

    // If all or part of the action is visible to the player, we need a message.
    bool      needs_message;
    bool      attacker_visible, defender_visible;
    bool      attacker_invisible, defender_invisible;

    // What was the monster's attitude when the attack began?
    mon_attitude_type defender_starting_attitude;

    bool      unarmed_ok;
    int       attack_number;

    int       to_hit;
    int       damage_done;
    int       special_damage;
    int       aux_damage;

    bool      stab_attempt;
    int       stab_bonus;

    int       min_delay;
    int       final_attack_delay;

    int       noise_factor;
    int       extra_noise;

    // Attacker's damage output potential:

    item_def  *weapon;
    int       damage_brand;  // Can be special even if unarmed (transforms)
    int       wpn_skill, hands;
    bool      hand_half_bonus;

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

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

    // Attack messages
    std::string attack_verb, verb_degree;
    std::string no_damage_message;
    std::string special_damage_message;
    std::string unarmed_attack;
    beam_type special_damage_flavour;

    item_def  *shield;
    item_def  *defender_shield;

    // Armour penalties?
    int       heavy_armour_penalty;
    bool      can_do_unarmed;

    // Attacker uses watery terrain to advantage vs defender. Implies that
    // both attacker and defender are in water.
    bool      water_attack;

    // 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;

public:
    melee_attack(actor *attacker, actor *defender,
                 bool allow_unarmed = true, int attack_num = -1);

    // Applies attack damage and other effects.
    bool attack();

    int  calc_to_hit(bool random = true);

    static std::string anon_name(description_level_type desc,
                                 bool actor_invisible);
    static std::string actor_name(const actor *a, description_level_type desc,
                                  bool actor_visible, bool actor_invisible);
    static std::string pronoun(const actor *a, pronoun_type ptyp,
                               bool actor_visible);
    static std::string anon_pronoun(pronoun_type ptyp);

private:
    void init_attack();
    bool is_banished(const actor *) const;
    bool is_water_attack(const actor *, const actor *) const;
    void check_hand_half_bonus_eligible();
    void check_autoberserk();
    bool check_unrand_effects(bool mondied = false);
    void emit_nodmg_hit_message();
    void identify_mimic(actor *mon);

    std::string debug_damage_number();
    std::string special_attack_punctuation();
    std::string attack_strength_punctuation();

    std::string atk_name(description_level_type desc) const;
    std::string def_name(description_level_type desc) const;
    std::string wep_name(description_level_type desc = DESC_NOCAP_YOUR,
                         unsigned long ignore_flags = ISFLAG_KNOW_CURSE
                                                    | ISFLAG_KNOW_PLUSES) const;

    bool attack_shield_blocked(bool verbose);
    bool apply_damage_brand();
    void calc_elemental_brand_damage(beam_type flavour,
                                     int res,
                                     const char *verb);
    int fire_res_apply_cerebov_downgrade(int res);
    void drain_defender();
    void rot_defender(int amount, int immediate = 0);
    void check_defender_train_armour();
    void check_defender_train_dodging();
    void splash_defender_with_acid(int strength);
    void splash_monster_with_acid(int strength);
    bool decapitate_hydra(int damage_done, int damage_type = -1);
    bool chop_hydra_head( int damage_done,
                          int dam_type,
                          int wpn_brand );

    // Returns true if the defender is banished.
    bool distortion_affects_defender();

    void chaos_affects_defender();
    void chaos_affects_attacker();
    void chaos_killed_defender(monsters* def_copy);
    int  random_chaos_brand();
    void do_miscast();

    std::vector<attack_final_effect> final_effects;

    void handle_noise(const coord_def & pos);

private:
    // Monster-attack specific stuff
    bool mons_attack_you();
    bool mons_attack_mons();
    int  mons_to_hit();
    bool mons_self_destructs();
    bool mons_attack_warded_off();
    int mons_attk_delay();
    int mons_calc_damage(const mon_attack_def &attk);
    void mons_apply_attack_flavour(const mon_attack_def &attk);
    int mons_apply_defender_ac(int damage, int damage_max);
    bool mons_perform_attack();
    void mons_perform_attack_rounds();
    void mons_check_attack_perceived();
    std::string mons_attack_verb(const mon_attack_def &attk);
    std::string mons_attack_desc(const mon_attack_def &attk);
    void mons_announce_hit(const mon_attack_def &attk);
    void mons_announce_dud_hit(const mon_attack_def &attk);
    void mons_set_weapon(const mon_attack_def &attk);
    void mons_do_poison(const mon_attack_def &attk);
    void mons_do_napalm();
    std::string mons_defender_name();
    void wasp_paralyse_defender();

    mon_attack_flavour random_chaos_attack_flavour();

private:
    // Player-attack specific stuff
    bool player_attack();
    bool player_aux_unarmed();
    bool player_apply_aux_unarmed();
    int  player_stat_modify_damage(int damage);
    int  player_aux_stat_modify_damage(int damage);
    int  player_to_hit(bool random_factor);
    void player_apply_attack_delay();
    int  player_apply_water_attack_bonus(int damage);
    int  player_apply_weapon_bonuses(int damage);
    int  player_apply_weapon_skill(int damage);
    int  player_apply_fighting_skill(int damage, bool aux);
    int  player_apply_misc_modifiers(int damage);
    int  player_apply_monster_ac(int damage);
    void player_weapon_auto_id();
    int  player_stab_weapon_bonus(int damage);
    int  player_stab(int damage);
    int  player_weapon_type_modify(int damage);

    bool player_hits_monster();
    int  player_calc_base_weapon_damage();
    int  player_calc_base_unarmed_damage();
    void player_exercise_combat_skills();
    bool player_monattk_final_hit_effects(bool mondied);
    bool player_monattk_hit_effects(bool mondied);
    void player_sustain_passive_damage();
    int  player_staff_damage(int skill);
    void player_apply_staff_damage();
    bool player_check_monster_died();
    void player_calc_hit_damage();
    void player_stab_check();
    int  player_weapon_speed();
    int  player_unarmed_speed();
    int  player_apply_shield_delay(int attack_delay);
    void player_announce_hit();
    std::string player_why_missed();
    void player_warn_miss();
    void player_check_weapon_effects();
    void _monster_die(monsters *monster, killer_type killer, int killer_index);
};

#endif