#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, MON_UNAFFECTED, MON_AFFECTED, MON_OTHER };
struct dist;
typedef FixedArray<int, 19, 19> explosion_map;
struct tracer_info
{
int count; int power; int hurt; int helped; bool dont_stop;
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
{
int range;
unsigned type; int colour;
beam_type flavour;
beam_type real_flavour; bool drop_item; item_def* item; coord_def source; coord_def target; dice_def damage;
int ench_power, hit;
killer_type thrower; int ex_size;
int beam_source; std::string name;
std::string short_name;
std::string hit_verb; bool is_beam; bool is_explosion;
bool is_big_cloud; bool aimed_at_spot; std::string aux_source;
bool affects_nothing; bool affects_items;
bool effect_known;
int draw_delay;
bolt* special_explosion;
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;
bool obvious_effect;
bool seen;
std::vector<coord_def> path_taken;
int range_used;
bool is_tracer; bool aimed_at_feet; bool msg_generated; bool passed_target; bool in_explosion_phase; bool smart_monster; bool can_see_invis; mon_attitude_type attitude; int foe_ratio;
tracer_info foe_info;
tracer_info friend_info;
bool chose_ray; bool beam_cancelled; bool dont_stop_player;
int bounces; coord_def bounce_pos;
int reflections; int reflector;
bool use_target_as_pos; bool auto_hit;
ray_def ray;
#ifdef USE_TILE
int tile_beam;
#endif
public:
bolt();
bool is_enchantment() const; void set_target(const dist &targ);
void set_agent(actor *agent);
void setup_retrace();
killer_type killer() const;
kill_category whose_kill() const;
actor* agent() const;
void fire();
std::string get_short_name() const;
mon_resist_type apply_enchantment_to_monster(monsters* mon);
bool explode(bool show_more = true, bool hole_in_the_middle = false);
private:
void do_fire();
coord_def pos() const;
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;
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();
void 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);
public:
void affect_cell(bool avoid_self = false);
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 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 nuke_wall_effect();
void drop_object();
void finish_beam();
bool fuzz_invis_tracer();
void internal_ouch(int dam);
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);
};
bool test_beam_hit(int attack, int defence);
int mons_adjust_flavoured(monsters *monster, bolt &pbolt, int hurted,
bool doFlavouredEffects = true);
bool enchant_monster_with_flavour(monsters* mon, actor *atk,
beam_type flavour, int powc = 0);
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