diff options
-rw-r--r-- | crawl-ref/source/beam.cc | 129 | ||||
-rw-r--r-- | crawl-ref/source/enum.h | 5 | ||||
-rw-r--r-- | crawl-ref/source/externs.h | 8 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.cc | 13 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 94 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.h | 2 |
6 files changed, 152 insertions, 99 deletions
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index 87953d540f..de4e421b9e 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -81,6 +81,7 @@ static int affect_player(struct bolt &beam); static void affect_items(struct bolt &beam, int x, int y); static int affect_monster(struct bolt &beam, struct monsters *mon); static int affect_monster_enchantment(struct bolt &beam, struct monsters *mon); +static void beam_paralyses_monster( bolt &pbolt, monsters *monster ); static int range_used_on_hit(struct bolt &beam); static void explosion1(struct bolt &pbolt); static void explosion_map(struct bolt &beam, int x, int y, @@ -89,6 +90,7 @@ static void explosion_cell(struct bolt &beam, int x, int y, bool drawOnly); static void ench_animation( int flavour, const monsters *mon = NULL, bool force = false); static void zappy(char z_type, int power, struct bolt &pbolt); +static void monster_die(monsters *mons, const bolt &beam); static std::set<std::string> beam_message_cache; @@ -101,6 +103,7 @@ static bool beam_is_blockable( struct bolt &pbolt ) && pbolt.flavour != BEAM_ELECTRICITY); } +// Kludge to suppress multiple redundant messages for a single beam. static void beam_mpr(int channel, const char *s, ...) { va_list args; @@ -118,6 +121,11 @@ static void beam_mpr(int channel, const char *s, ...) beam_message_cache.insert( message ); } +static void monster_die(monsters *mons, const bolt &beam) +{ + monster_die(mons, beam.killer(), beam.beam_source); +} + // simple animated flash from Rupert Smith (and expanded to be more generic): void zap_animation( int colour, const monsters *mon, bool force ) { @@ -1848,9 +1856,6 @@ bool mass_enchantment( int wh_enchant, int pow, int origin ) */ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt) { - bool is_near = mons_near(monster); // single caluclation permissible {dlb} - char buff[ ITEMNAME_SIZE ]; - switch (pbolt.flavour) /* put in magic resistance */ { case BEAM_SLOW: /* 0 = slow monster */ @@ -1904,7 +1909,7 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt) if (monster->hit_points == monster->max_hit_points) { if (simple_monster_message(monster, - "'s wounds heal themselves!")) + "'s wounds heal themselves!")) pbolt.obvious_effect = true; } else @@ -1916,38 +1921,7 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt) return (MON_AFFECTED); case BEAM_PARALYSIS: /* 3 = paralysis */ - monster->speed_increment = 0; - - if (simple_monster_message(monster, " suddenly stops moving!")) - pbolt.obvious_effect = true; - - if (grd[monster->x][monster->y] == DNGN_LAVA - || grid_is_water(grd[monster->x][monster->y])) - { - if (mons_flies(monster) == 1) - { - // don't worry about invisibility - you should be able to - // see if something has fallen into the lava - if (is_near) - mprf("%s falls into the %s!", - ptr_monam(monster, DESC_CAP_THE), - (grd[monster->x][monster->y] == DNGN_LAVA) ? "lava" : - "water"); - - switch (pbolt.thrower) - { - case KILL_YOU: - case KILL_YOU_MISSILE: - monster_die(monster, KILL_YOU, pbolt.beam_source); - break; /* " " */ - - case KILL_MON: - case KILL_MON_MISSILE: - monster_die(monster, KILL_MON_MISSILE, pbolt.beam_source); - break; /* dragon breath &c */ - } - } - } + beam_paralyses_monster(pbolt, monster); return (MON_AFFECTED); case BEAM_CONFUSION: /* 4 = confusion */ @@ -1962,24 +1936,26 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt) case BEAM_INVISIBILITY: /* 5 = invisibility */ // Store the monster name before it becomes an "it" -- bwr - strncpy( buff, ptr_monam( monster, DESC_CAP_THE ), sizeof(buff) ); - - if (mons_add_ench(monster, ENCH_INVIS)) + { + const std::string monster_name = ptr_monam(monster, DESC_CAP_THE); + + if (!mons_has_ench(monster, ENCH_INVIS) + && mons_add_ench(monster, ENCH_INVIS)) { // Can't use simple_monster_message here, since it checks // for visibility of the monster (and its now invisible) -- bwr if (mons_near( monster )) { - snprintf( info, INFO_SIZE, "%s flickers %s", - buff, player_see_invis() ? "for a moment." - : "and vanishes!" ); - mpr( info ); + mprf("%s flickers %s", + monster_name.c_str(), + player_see_invis() ? "for a moment." + : "and vanishes!" ); } pbolt.obvious_effect = true; } return (MON_AFFECTED); - + } case BEAM_CHARM: /* 9 = charm */ if (mons_add_ench(monster, ENCH_CHARM)) { @@ -2001,13 +1977,40 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt) } // end mons_ench_f2() // degree is ignored. -static void slow_monster(monsters *mon, int degree) +static void slow_monster(monsters *mon, int /* degree */) { bolt beam; beam.flavour = BEAM_SLOW; mons_ench_f2(mon, beam); } +static void beam_paralyses_monster(bolt &pbolt, monsters *monster) +{ + if (!mons_has_ench(monster, ENCH_PARALYSIS) + && mons_add_ench(monster, ENCH_PARALYSIS)) + { + if (simple_monster_message(monster, " suddenly stops moving!")) + pbolt.obvious_effect = true; + + const int grid = grd(monster->pos()); + + if (grid == DNGN_LAVA || grid_is_water(grid)) + { + if (mons_flies(monster) == 1) + { + // don't worry about invisibility - you should be able to + // see if something has fallen into the lava + if (mons_near(monster)) + mprf("%s falls into the %s!", + ptr_monam(monster, DESC_CAP_THE), + (grid == DNGN_LAVA ? "lava" : "water")); + + monster_die(monster, pbolt); + } + } + } +} + // Returns true if the curare killed the monster. bool curare_hits_monster( const bolt &beam, monsters *monster, @@ -2032,9 +2035,7 @@ bool curare_hits_monster( const bolt &beam, simple_monster_message(monster, " convulses."); if ((monster->hit_points -= hurted) < 1) { - const int thrower = YOU_KILL(beam.thrower) ? - KILL_YOU_MISSILE : KILL_MON_MISSILE; - monster_die(monster, thrower, beam.beam_source); + monster_die(monster, beam); mondied = true; } } @@ -3429,7 +3430,7 @@ static int affect_monster(struct bolt &beam, struct monsters *mon) } beam.obvious_effect = true; mon->hit_points = 0; - monster_die(mon, thrower, beam.beam_source); + monster_die(mon, beam); return (BEAM_STOP); } @@ -3647,7 +3648,7 @@ static int affect_monster(struct bolt &beam, struct monsters *mon) if (mon->hit_points < 1) { - monster_die(mon, thrower, beam.beam_source); + monster_die(mon, beam); } else { @@ -3754,7 +3755,7 @@ static int affect_monster_enchantment(struct bolt &beam, struct monsters *mon) simple_monster_message(mon, " wobbles for a moment."); } else - monster_die(mon, KILL_RESET, beam.beam_source); + monster_die(mon, beam); beam.obvious_effect = true; return (MON_AFFECTED); @@ -3913,12 +3914,8 @@ static int affect_monster_enchantment(struct bolt &beam, struct monsters *mon) deathCheck: - int thrower = KILL_YOU_MISSILE; - if (MON_KILL(beam.thrower)) - thrower = KILL_MON_MISSILE; - if (mon->hit_points < 1) - monster_die(mon, thrower, beam.beam_source); + monster_die(mon, beam); else { print_wounds(mon); @@ -4405,6 +4402,26 @@ bolt::bolt() : range(0), rangeMax(0), type(SYM_ZAP), colour(BLACK), chose_ray(false) { } +int bolt::killer() const +{ + if (flavour == BEAM_BANISH) + return (KILL_RESET); + + switch (thrower) + { + case KILL_YOU: + case KILL_YOU_MISSILE: + return (flavour == BEAM_PARALYSIS? KILL_YOU : KILL_YOU_MISSILE); + + case KILL_MON: + case KILL_MON_MISSILE: + return (KILL_MON_MISSILE); + + default: + return (KILL_MON_MISSILE); + } +} + void bolt::set_target(const dist &d) { if (!d.isValid) diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index 1bcc8e7a0e..4c19fd10f4 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -1221,7 +1221,10 @@ enum enchant_type ENCH_CREATED_FRIENDLY, // no longer used ENCH_SLEEP_WARY, ENCH_SUBMERGED, // 73 (includes air elementals in air) - ENCH_SHORT_LIVED, // 74 for ball lightning + ENCH_SHORT_LIVED, // 74 for ball lightning + + ENCH_PARALYSIS, + NUM_ENCHANTMENTS }; diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h index 8db5af8ee5..5d53e443fe 100644 --- a/crawl-ref/source/externs.h +++ b/crawl-ref/source/externs.h @@ -255,6 +255,9 @@ public: bolt(); void set_target(const dist &); + + // Returns YOU_KILL or MON_KILL, depending on the source of the beam. + int killer() const; }; struct run_check_dir @@ -621,6 +624,11 @@ struct monsters // once they go out of sight god_type god; // Usually GOD_NO_GOD. + + coord_def pos() const + { + return coord_def(x, y); + } }; struct cloud_struct diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 2a7463de49..b0733fe0c9 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -1693,13 +1693,12 @@ bool mons_friendly(const monsters *m) bool mons_is_submerged( const monsters *mon ) { // FIXME, switch to 4.1's MF_SUBMERGED system which is much cleaner. - return (mons_has_ench( mon, ENCH_SUBMERGED )); + return (mons_has_ench(mon, ENCH_SUBMERGED)); } bool mons_is_paralysed(const monsters *m) { - // maybe this should be 70 - return (m->speed_increment <= 60); + return (mons_has_ench(m, ENCH_PARALYSIS)); } bool mons_is_confused(const monsters *m) @@ -1844,6 +1843,14 @@ int mons_del_ench( struct monsters *mon, unsigned int ench, unsigned int ench2, mon->speed *= 2; } + if (ench == ENCH_PARALYSIS) + { + if (!quiet) + simple_monster_message(mon, " is no longer paralysed."); + + behaviour_event(mon, ME_EVAL); + } + if (ench == ENCH_FEAR) { if (!quiet) diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index dc56a2b137..d0f2095504 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -328,7 +328,7 @@ static void place_monster_corpse(const monsters *monster) learned_something_new(TUT_MAKE_CHUNKS); } // end place_monster_corpse() -void monster_die(struct monsters *monster, char killer, int i) +void monster_die(monsters *monster, char killer, int i) { int dmi; // dead monster's inventory int xom_will_act = 0; @@ -1855,6 +1855,11 @@ static bool handle_enchantment(struct monsters *monster) mons_del_ench(monster, ENCH_FEAR); break; + case ENCH_PARALYSIS: + if (random2(120) < mod_speed( monster->hit_dice + 5, speed )) + mons_del_ench(monster, ENCH_PARALYSIS); + break; + case ENCH_CONFUSION: if (random2(120) < mod_speed( monster->hit_dice + 5, speed )) { @@ -3576,6 +3581,48 @@ static bool handle_monster_spell(monsters *monster, bolt &beem) return (false); } +// Give the monster its action energy (aka speed_increment). +static void monster_add_energy(monsters *monster) +{ + int energy_gained = (monster->speed * you.time_taken) / 10; + + // Slow monsters might get 0 here. Maybe we should factor in + // *how* slow it is...but a 10-to-1 move ratio seems more than + // enough. + if ( energy_gained == 0 && monster->speed != 0 ) + energy_gained = 1; + + monster->speed_increment += energy_gained; + + if (you.slow > 0) + monster->speed_increment += energy_gained; +} + +// Do natural regeneration for monster. +static void monster_regenerate(monsters *monster) +{ + // regenerate: + if (monster_descriptor(monster->type, MDSC_REGENERATES) + + || (monster->type == MONS_FIRE_ELEMENTAL + && (grd[monster->x][monster->y] == DNGN_LAVA + || env.cgrid[monster->x][monster->y] == CLOUD_FIRE + || env.cgrid[monster->x][monster->y] == CLOUD_FIRE_MON)) + + || (monster->type == MONS_WATER_ELEMENTAL + && (grd[monster->x][monster->y] == DNGN_SHALLOW_WATER + || grd[monster->x][monster->y] == DNGN_DEEP_WATER)) + + || (monster->type == MONS_AIR_ELEMENTAL + && env.cgrid[monster->x][monster->y] == EMPTY_CLOUD + && one_chance_in(3)) + + || one_chance_in(25)) + { + heal_monster(monster, 1, false); + } +} + static void handle_monster_move(int i, monsters *monster) { bool brkk = false; @@ -3592,20 +3639,7 @@ static void handle_monster_move(int i, monsters *monster) return; } - int energy_gained = (monster->speed * you.time_taken) / 10; - - // Slow monsters might get 0 here. Maybe we should factor in - // *how* slow it is...but a 10-to-1 move ratio seems more than - // enough. - if ( energy_gained == 0 && monster->speed != 0 ) - energy_gained = 1; - - monster->speed_increment += energy_gained; - - if (you.slow > 0) - { - monster->speed_increment += energy_gained; - } + monster_add_energy(monster); // Handle enchantments and clouds on nonmoving monsters: if (monster->speed == 0) @@ -3666,11 +3700,16 @@ static void handle_monster_move(int i, monsters *monster) } } - handle_behaviour(monster); - if (handle_enchantment(monster)) continue; + monster_regenerate(monster); + + if (mons_is_paralysed(monster)) + continue; + + handle_behaviour(monster); + // submerging monsters will hide from clouds if (monster_can_submerge(monster->type, grd[monster->x][monster->y]) && env.cgrid[monster->x][monster->y] != EMPTY_CLOUD) @@ -3678,27 +3717,6 @@ static void handle_monster_move(int i, monsters *monster) mons_add_ench( monster, ENCH_SUBMERGED ); } - // regenerate: - if (monster_descriptor(monster->type, MDSC_REGENERATES) - - || (monster->type == MONS_FIRE_ELEMENTAL - && (grd[monster->x][monster->y] == DNGN_LAVA - || env.cgrid[monster->x][monster->y] == CLOUD_FIRE - || env.cgrid[monster->x][monster->y] == CLOUD_FIRE_MON)) - - || (monster->type == MONS_WATER_ELEMENTAL - && (grd[monster->x][monster->y] == DNGN_SHALLOW_WATER - || grd[monster->x][monster->y] == DNGN_DEEP_WATER)) - - || (monster->type == MONS_AIR_ELEMENTAL - && env.cgrid[monster->x][monster->y] == EMPTY_CLOUD - && one_chance_in(3)) - - || one_chance_in(25)) - { - heal_monster(monster, 1, false); - } - if (monster->speed >= 100) continue; diff --git a/crawl-ref/source/monstuff.h b/crawl-ref/source/monstuff.h index dbbb85aeae..333abfdfd8 100644 --- a/crawl-ref/source/monstuff.h +++ b/crawl-ref/source/monstuff.h @@ -45,7 +45,7 @@ bool monster_polymorph(struct monsters *monster, int targetc, int power); * called from: bang - beam - effects - fight - misc - monstuff - mstuff2 - * spells1 - spells2 - spells3 - spells4 * *********************************************************************** */ -void monster_die(struct monsters *monster, char killer, int i); +void monster_die(monsters *monster, char killer, int i); // last updated: 17dec2000 {gdl} /* *********************************************************************** |