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