summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2007-10-14 04:09:48 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2007-10-14 04:09:48 +0000
commitb50185bac38de855ff1423242390d338ee35045f (patch)
treef75a91f45515ca74cdaad6684e125d1128210de0
parentbd19eb507dcd40d235ab26ae68c7d091aaeecb65 (diff)
downloadcrawl-ref-b50185bac38de855ff1423242390d338ee35045f.tar.gz
crawl-ref-b50185bac38de855ff1423242390d338ee35045f.zip
handle_monster_move() still wasn't dealing quite right with invoking
apply_enchantments(), since a monster could have apply_enchantments() not called for a normal-speed player turn, and then get called twice in a row during the next turn. This fix also makes zero-speed monsters like plants have apply_enchantments() be handled the same way as other monsters, so enchantments are now allways processed in time increments of 10 energy units (cloud processing for zero speed monsters is still handled separately, though). git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@2456 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r--crawl-ref/source/mon-util.cc49
-rw-r--r--crawl-ref/source/monstuff.cc169
2 files changed, 71 insertions, 147 deletions
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 8428a4f0a7..ed5f52174d 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -3896,28 +3896,20 @@ void monsters::add_enchantment_effect(const mon_enchant &ench, bool quiet)
break;
case ENCH_HASTE:
- {
- int old_speed = speed;
if (speed >= 100)
speed = 100 + ((speed - 100) * 2);
else
speed *= 2;
- ench_countdown = div_rand_round(ench_countdown * speed, old_speed);
break;
- }
case ENCH_SLOW:
- {
- int old_speed = speed;
if (speed >= 100)
speed = 100 + ((speed - 100) / 2);
else
speed /= 2;
- ench_countdown = div_rand_round(ench_countdown * speed, old_speed);
break;
- }
case ENCH_SUBMERGED:
if (type == MONS_AIR_ELEMENTAL && mons_near(this) && !quiet)
@@ -3952,28 +3944,20 @@ void monsters::remove_enchantment_effect(const mon_enchant &me, bool quiet)
break;
case ENCH_HASTE:
- {
- int old_speed = speed;
if (speed >= 100)
speed = 100 + ((speed - 100) / 2);
else
speed /= 2;
- ench_countdown = div_rand_round(ench_countdown * speed, old_speed);
break;
- }
case ENCH_SLOW:
- {
- int old_speed = speed;
if (speed >= 100)
speed = 100 + ((speed - 100) * 2);
else
speed *= 2;
- ench_countdown = div_rand_round(ench_countdown * speed, old_speed);
break;
- }
case ENCH_PARALYSIS:
if (!quiet)
@@ -4235,11 +4219,11 @@ std::string monsters::describe_enchantments() const
return (oss.str());
}
-// used to adjust time durations in handle_enchantment() for monster speed
+// used to adjust time durations in calc_duration() for monster speed
static inline int mod_speed( int val, int speed )
{
if (!speed)
- speed = you.time_taken;
+ speed = 10;
const int modded = (speed ? (val * 10) / speed : val);
return (modded? modded : 1);
}
@@ -4247,9 +4231,8 @@ static inline int mod_speed( int val, int speed )
bool monsters::decay_enchantment(const mon_enchant &me, bool decay_degree)
{
// Faster monsters can wiggle out of the net more quickly.
- const int spd = (speed == 0) ? you.time_taken :
- (me.ench == ENCH_HELD) ? speed :
- 10;
+ const int spd = (me.ench == ENCH_HELD) ? speed :
+ 10;
const int actdur = speed_to_duration(spd);
if (lose_ench_duration(me, actdur))
return (true);
@@ -4284,7 +4267,7 @@ bool monsters::decay_enchantment(const mon_enchant &me, bool decay_degree)
void monsters::apply_enchantment(const mon_enchant &me)
{
- const int spd = speed == 0? you.time_taken : 10;
+ const int spd = 10;
switch (me.ench)
{
case ENCH_BERSERK:
@@ -4485,11 +4468,11 @@ void monsters::apply_enchantment(const mon_enchant &me)
break;
else if (((type == MONS_ELECTRICAL_EEL
|| type == MONS_LAVA_SNAKE)
- && (random2(1000) < mod_speed( 20, spd )
+ && (random2(1000) < 20
|| (mons_near(this)
&& hit_points == max_hit_points
&& !one_chance_in(10))))
- || random2(2000) < mod_speed(10, spd)
+ || random2(2000) < 10
|| (mons_near(this)
&& hit_points == max_hit_points
&& !one_chance_in(5)))
@@ -4509,12 +4492,6 @@ void monsters::apply_enchantment(const mon_enchant &me)
if (mons_res_poison(this) < 0)
dam += roll_dice( 2, poisonval ) - 1;
- // We adjust damage for monster speed (since this is applied
- // only when the monster moves), and we handle the factional
- // part as well (so that speed 30 creatures will take damage).
- dam *= 10;
- dam = (dam / spd) + ((random2(spd) < (dam % spd)) ? 1 : 0);
-
if (dam > 0)
{
hurt_monster( this, dam );
@@ -4539,7 +4516,7 @@ void monsters::apply_enchantment(const mon_enchant &me)
case ENCH_ROT:
{
if (hit_points > 1
- && random2(1000) < mod_speed( 333, spd ))
+ && random2(1000) < 333)
{
hurt_monster(this, 1);
if (hit_points < max_hit_points && coinflip())
@@ -4558,12 +4535,6 @@ void monsters::apply_enchantment(const mon_enchant &me)
if (mons_res_fire( this ) < 0)
dam += roll_dice( 2, 5 ) - 1;
- // We adjust damage for monster speed (since this is applied
- // only when the monster moves), and we handle the factional
- // part as well (so that speed 30 creatures will take damage).
- dam *= 10;
- dam = (dam / spd) + ((random2(spd) < (dam % spd)) ? 1 : 0);
-
if (dam > 0)
{
hurt_monster( this, dam );
@@ -4593,7 +4564,7 @@ void monsters::apply_enchantment(const mon_enchant &me)
case ENCH_GLOWING_SHAPESHIFTER: // this ench never runs out
// number of actions is fine for shapeshifters
if (type == MONS_GLOWING_SHAPESHIFTER
- || random2(1000) < mod_speed( 250, spd ))
+ || random2(1000) < 250)
{
monster_polymorph(this, RANDOM_MONSTER, PPT_SAME);
}
@@ -4601,7 +4572,7 @@ void monsters::apply_enchantment(const mon_enchant &me)
case ENCH_SHAPESHIFTER: // this ench never runs out
if (type == MONS_SHAPESHIFTER
- || random2(1000) < mod_speed( 1000 / ((15 * hit_dice) / 5), spd ))
+ || random2(1000) < ( 1000 / ((15 * hit_dice) / 5)))
{
monster_polymorph(this, RANDOM_MONSTER, PPT_SAME);
}
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index b3a2eb4995..15efbd4177 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -1171,7 +1171,6 @@ bool monster_polymorph( monsters *monster, monster_type targetc,
const int old_hp_max = monster->max_hit_points;
const bool old_mon_caught = mons_is_caught(monster);
const char old_ench_countdown = monster->ench_countdown;
- const int old_speed = monster->speed;
/* deal with mons_sec */
monster->type = targetc;
@@ -1187,8 +1186,7 @@ bool monster_polymorph( monsters *monster, monster_type targetc,
monster->add_ench(abj);
monster->add_ench(shifter);
- monster->ench_countdown = old_ench_countdown * old_speed
- / monster->speed;
+ monster->ench_countdown = old_ench_countdown;
if (mons_class_flag( monster->type, M_INVIS ))
monster->add_ench(ENCH_INVIS);
@@ -2139,40 +2137,6 @@ bool simple_monster_message(const monsters *monster, const char *event,
return (false);
} // end simple_monster_message()
-static bool handle_enchantment(monsters *monster)
-{
- // Yes, this is the speed we want. This function will be called in
- // two circumstances: (1) the monster can move and has enough energy,
- // and (2) the monster cannot move (speed == 0) and the monster loop
- // is running.
- //
- // In the first case we in the player's time by keeping track of
- // how much energy the monster has expended since the last time
- // apply_enchantments() was called, and calling it each time that
- // it equals or exceeds the monsters speed. For example, a bat
- // gets 30 energy points for every 10 the player gets, and each
- // time it spends 30 energy points apply_enchantments() is called.
- //
- // In the second case, we're hacking things so that plants can suffer
- // from sticky flame. The rate of call in this case is once every
- // player action... so the time_taken by the player is the ratio to
- // the absolute time frame.
- //
- // -- bwr
- if (monster->speed == 0)
- monster->apply_enchantments();
- else
- {
- while (monster->ench_countdown <= 0)
- {
- monster->apply_enchantments();
- monster->ench_countdown += monster->speed;
- }
- }
-
- return (!monster->alive());
-} // end handle_enchantment()
-
//---------------------------------------------------------------
//
// handle_movement
@@ -3930,34 +3894,17 @@ static void monster_regenerate(monsters *monster)
}
}
-static void handle_ench_countdown(monsters *monster, int &old_energy)
+static void swim_or_move_energy(monsters *mon)
{
- // Paranoia
- if (monster->speed_increment >= old_energy)
+ monsterentry *entry = get_monster_data(mon->type);
+ dungeon_feature_type feat = grd[mon->x][mon->y];
+ if (feat >= DNGN_LAVA && feat <= DNGN_SHALLOW_WATER
+ && !mon->airborne())
{
-#if DEBUG
- if (monster->speed_increment == old_energy)
- mprf(MSGCH_DIAGNOSTICS,
- "Monster '%s' has same energy as last iteration.",
- monster->name(DESC_PLAIN).c_str(), true);
- else
- mprf(MSGCH_DIAGNOSTICS,
- "Monster '%s' has MORE energy than last iteration.",
- monster->name(DESC_PLAIN).c_str(), true);
-#endif
-
- monster->speed_increment = old_energy - 10;
- monster->ench_countdown -= 10;
+ mon->speed_increment -= entry->energy_usage.swim;
}
else
- {
- if (old_energy != INT_MAX)
- {
- int energy_spent = old_energy - monster->speed_increment;
- monster->ench_countdown -= energy_spent;
- }
- }
- old_energy = monster->speed_increment;
+ mon->speed_increment -= entry->energy_usage.move;
}
#if DEBUG
@@ -3988,7 +3935,7 @@ static void handle_monster_move(int i, monsters *monster)
monster_add_energy(monster);
- // Handle enchantments and clouds on nonmoving monsters:
+ // Handle clouds on nonmoving monsters:
if (monster->speed == 0)
{
if (env.cgrid[monster->x][monster->y] != EMPTY_CLOUD
@@ -3996,9 +3943,23 @@ static void handle_monster_move(int i, monsters *monster)
{
mons_in_cloud( monster );
}
+ }
- if (handle_enchantment( monster ))
- return;
+ // Apply monster enchantments once for every normal-speed
+ // player turn.
+ monster->ench_countdown -= you.time_taken;
+ if (you.duration[DUR_SLOW] > 0)
+ monster->ench_countdown -= you.time_taken;
+ while (monster->ench_countdown < 0)
+ {
+ monster->ench_countdown += 10;
+ monster->apply_enchantments();
+
+ // Don't return if the monster died, since we have to deal
+ // with giant spores and ball lightning exploding at the
+ // end of the function.
+ if (!monster->alive())
+ break;
}
// memory is decremented here for a reason -- we only want it
@@ -4029,18 +3990,29 @@ static void handle_monster_move(int i, monsters *monster)
monsterentry* entry = get_monster_data(monster->type);
int old_energy = INT_MAX;
- int non_move_energy = std::min(entry->energy_usage.move,
- entry->energy_usage.swim);
+ int non_move_energy = std::min(entry->energy_usage.move,
+ entry->energy_usage.swim);
while (monster->has_action_energy())
{ // The continues & breaks are WRT this.
if (!monster->alive())
break;
- if (handle_enchantment(monster))
- break;
-
- handle_ench_countdown(monster, old_energy);
+ if (monster->speed_increment >= old_energy)
+ {
+#if DEBUG
+ if (monster->speed_increment == old_energy)
+ mprf(MSGCH_DIAGNOSTICS, "'%s' has same energy as last loop",
+ monster->name(DESC_PLAIN, true).c_str());
+ else
+ mprf(MSGCH_DIAGNOSTICS, "'%s' has MORE energy than last loop",
+ monster->name(DESC_PLAIN, true).c_str());
+#endif
+ monster->speed_increment = old_energy - 10;
+ old_energy = monster->speed_increment;
+ continue;
+ }
+ old_energy = monster->speed_increment;
if (env.cgrid[monster->x][monster->y] != EMPTY_CLOUD)
{
@@ -4119,7 +4091,10 @@ static void handle_monster_move(int i, monsters *monster)
}
}
- if (!mons_is_caught(monster))
+ if (mons_is_caught(monster))
+ // Struggling against the net takes time.
+ swim_or_move_energy(monster);
+ else
{
// calculates mmov_x, mmov_y based on monster target.
handle_movement(monster);
@@ -4341,28 +4316,22 @@ static void handle_monster_move(int i, monsters *monster)
} // end while
-
- if (monster->type != -1)
+ if (monster->type != -1 && monster->hit_points < 1)
{
- if ( monster->hit_points >= 1)
- handle_ench_countdown(monster, old_energy);
- else
+ if (monster->type == MONS_GIANT_SPORE
+ || monster->type == MONS_BALL_LIGHTNING)
{
- if (monster->type == MONS_GIANT_SPORE
- || monster->type == MONS_BALL_LIGHTNING)
- {
- // detach monster from the grid first, so it
- // doesn't get hit by its own explosion (GDL)
- mgrd[monster->x][monster->y] = NON_MONSTER;
+ // detach monster from the grid first, so it
+ // doesn't get hit by its own explosion (GDL)
+ mgrd[monster->x][monster->y] = NON_MONSTER;
- spore_goes_pop( monster );
- monster_cleanup( monster );
- return;
- }
- else
- {
- monster_die( monster, KILL_MISC, 0 );
- }
+ spore_goes_pop( monster );
+ monster_cleanup( monster );
+ return;
+ }
+ else
+ {
+ monster_die( monster, KILL_MISC, 0 );
}
}
}
@@ -4658,15 +4627,7 @@ static bool monster_swaps_places( monsters *mon, int mx, int my )
return (false);
// Okay, do the swap!
- monsterentry *entry = get_monster_data(mon->type);
- dungeon_feature_type feat = grd[mon->x][mon->y];
- if (feat >= DNGN_LAVA && feat <= DNGN_SHALLOW_WATER
- && !mon->airborne())
- {
- mon->speed_increment -= entry->energy_usage.swim;
- }
- else
- mon->speed_increment -= entry->energy_usage.move;
+ swim_or_move_energy(mon);
mon->x = nx;
mon->y = ny;
@@ -4717,15 +4678,7 @@ static bool do_move_monster(monsters *monster, int xi, int yi)
return false;
/* this appears to be the real one, ie where the movement occurs: */
- monsterentry *entry = get_monster_data(monster->type);
- dungeon_feature_type feat = grd[monster->x][monster->y];
- if (feat >= DNGN_LAVA && feat <= DNGN_SHALLOW_WATER
- && !monster->airborne())
- {
- monster->speed_increment -= entry->energy_usage.swim;
- }
- else
- monster->speed_increment -= entry->energy_usage.move;
+ swim_or_move_energy(monster);
mgrd[monster->x][monster->y] = NON_MONSTER;