summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-02-10 09:13:01 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-02-10 09:13:01 +0000
commitadbc8a9292e59d53a7fead4daea84f08909af94f (patch)
tree2f333a78450a3703b358be031317da2dc00be34f /crawl-ref/source
parent45835f326479addd1bfdc2d3d5bd3e175f9319aa (diff)
downloadcrawl-ref-adbc8a9292e59d53a7fead4daea84f08909af94f.tar.gz
crawl-ref-adbc8a9292e59d53a7fead4daea84f08909af94f.zip
Handle monster paralysis as an enchantment instead of the old speed mangling
hack. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@949 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/beam.cc129
-rw-r--r--crawl-ref/source/enum.h5
-rw-r--r--crawl-ref/source/externs.h8
-rw-r--r--crawl-ref/source/mon-util.cc13
-rw-r--r--crawl-ref/source/monstuff.cc94
-rw-r--r--crawl-ref/source/monstuff.h2
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}
/* ***********************************************************************