summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorharanp <haranp@c06c8d41-db1a-0410-9941-cceddc491573>2008-10-04 14:44:13 +0000
committerharanp <haranp@c06c8d41-db1a-0410-9941-cceddc491573>2008-10-04 14:44:13 +0000
commit4d0b7c461fd459e01cab475eb6b01ab5ea9d4689 (patch)
tree3750b8574e0cba9afe96292cf622c385a30ce62e
parentda0c3f0c317cfb21e88aecbbb90388cc6d087cfe (diff)
downloadcrawl-ref-4d0b7c461fd459e01cab475eb6b01ab5ea9d4689.tar.gz
crawl-ref-4d0b7c461fd459e01cab475eb6b01ab5ea9d4689.zip
Redid monster death idiom so that monsters::hurt can implicitly
call monster_die(). (This behaviour can be overriden.) Minor code cleanups elsewhere, removal of dead code from bolt. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7123 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r--crawl-ref/source/beam.cc385
-rw-r--r--crawl-ref/source/beam.h62
-rw-r--r--crawl-ref/source/effects.cc36
-rw-r--r--crawl-ref/source/enum.h56
-rw-r--r--crawl-ref/source/externs.h10
-rw-r--r--crawl-ref/source/fight.cc20
-rw-r--r--crawl-ref/source/items.cc4
-rw-r--r--crawl-ref/source/mon-util.cc30
-rw-r--r--crawl-ref/source/monstuff.cc12
-rw-r--r--crawl-ref/source/monstuff.h3
-rw-r--r--crawl-ref/source/mstuff2.cc1
-rw-r--r--crawl-ref/source/ouch.cc6
-rw-r--r--crawl-ref/source/player.cc4
-rw-r--r--crawl-ref/source/spells2.cc33
-rw-r--r--crawl-ref/source/spells3.cc14
-rw-r--r--crawl-ref/source/spells4.cc48
-rw-r--r--crawl-ref/source/spl-cast.cc5
-rw-r--r--crawl-ref/source/stuff.cc10
-rw-r--r--crawl-ref/source/stuff.h2
-rw-r--r--crawl-ref/source/traps.cc10
20 files changed, 305 insertions, 446 deletions
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index d5324c22fd..8968e408e6 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -61,10 +61,6 @@
#define BEAM_STOP 1000 // all beams stopped by subtracting this
// from remaining range
-#define MON_RESIST 0 // monster resisted
-#define MON_UNAFFECTED 1 // monster unaffected
-#define MON_AFFECTED 2 // monster was affected
-#define MON_OTHER 3 // monster unaffected, but for other reasons
static FixedArray < bool, 19, 19 > explode_map;
@@ -80,7 +76,7 @@ static int _affect_place_clouds(bolt &beam, const coord_def& p);
static void _affect_place_explosion_clouds(bolt &beam, const coord_def& p);
static int _affect_player(bolt &beam, item_def *item = NULL);
static int _affect_monster(bolt &beam, monsters *mon, item_def *item = NULL);
-static int _affect_monster_enchantment(bolt &beam, monsters *mon);
+static mon_resist_type _affect_monster_enchantment(bolt &beam, monsters *mon);
static void _beam_paralyses_monster( bolt &pbolt, monsters *monster );
static void _beam_petrifies_monster( bolt &pbolt, monsters *monster );
static int _range_used_on_hit(bolt &beam);
@@ -93,9 +89,8 @@ static void _explosion_cell(bolt &beam, const coord_def& p, bool drawOnly,
static void _ench_animation(int flavour, const monsters *mon = NULL,
bool force = false);
static void _zappy(zap_type z_type, int power, bolt &pbolt);
-static void _monster_die(monsters *mons, const bolt &beam);
-static bool _nasty_beam(monsters *mon, bolt &beam);
-static bool _nice_beam(monsters *mon, bolt &beam);
+static bool _nasty_beam(monsters *mon, const bolt &beam);
+static bool _nice_beam(monsters *mon, const bolt &beam);
static std::set<std::string> beam_message_cache;
@@ -126,11 +121,6 @@ static void _beam_mpr(msg_channel_type 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);
-}
-
static kill_category _whose_kill(const bolt &beam)
{
if (YOU_KILL(beam.thrower))
@@ -1512,7 +1502,7 @@ static bool _affect_mon_in_wall(bolt &pbolt, item_def *item,
if (mid == NON_MONSTER)
return (false);
- if (pbolt.is_enchant
+ if (pbolt.is_enchantment()
|| (!pbolt.is_explosion && !pbolt.is_big_cloud
&& (grd(where) == DNGN_METAL_WALL
|| pbolt.flavour != BEAM_ELECTRICITY)))
@@ -1738,7 +1728,7 @@ void fire_beam(bolt &pbolt, item_def *item, bool drop_item)
// Actually draw the beam/missile/whatever,
// if the player can see the cell.
- if (!pbolt.is_tracer && pbolt.name[0] != '0' && see_grid(testpos))
+ if (!pbolt.is_tracer && !pbolt.is_enchantment() && see_grid(testpos))
{
// We don't clean up the old position.
// First, most people like to see the full path,
@@ -1775,7 +1765,7 @@ void fire_beam(bolt &pbolt, item_def *item, bool drop_item)
#ifdef MISSILE_TRAILS_OFF
// mv: It's not optimal but is usually enough.
- if (!pbolt.is_beam || pbolt.name[0] == '0')
+ if (!pbolt.is_beam || pbolt.is_enchantment())
viewwindow(true, false);
#endif
}
@@ -1810,7 +1800,7 @@ void fire_beam(bolt &pbolt, item_def *item, bool drop_item)
// Canned msg for enchantments that affected no-one, but only if the
// enchantment is yours.
- if (pbolt.name[0] == '0')
+ if (pbolt.is_enchantment())
{
if (!pbolt.is_tracer && !pbolt.msg_generated && !pbolt.obvious_effect
&& YOU_KILL(pbolt.thrower))
@@ -2283,7 +2273,7 @@ bool mass_enchantment( enchant_type wh_enchant, int pow, int origin,
// * Returns MON_RESIST if monster is unaffected due to magic resist.
// * Returns MON_UNAFFECTED if monster is immune to enchantment.
// * Returns MON_AFFECTED in all other cases (already enchanted, etc).
-int mons_ench_f2(monsters *monster, bolt &pbolt)
+mon_resist_type mons_ench_f2(monsters *monster, bolt &pbolt)
{
switch (pbolt.flavour) // put in magic resistance
{
@@ -2338,11 +2328,11 @@ int mons_ench_f2(monsters *monster, bolt &pbolt)
case BEAM_HEALING:
if (YOU_KILL(pbolt.thrower))
{
- if (cast_healing(5 + roll_dice( pbolt.damage ), monster->pos()) > 0)
+ if (cast_healing(5 + pbolt.damage.roll(), monster->pos()) > 0)
pbolt.obvious_effect = true;
pbolt.msg_generated = true; // to avoid duplicate "nothing happens"
}
- else if (heal_monster( monster, 5 + roll_dice( pbolt.damage ), false ))
+ else if (heal_monster( monster, 5 + pbolt.damage.roll(), false ))
{
if (monster->hit_points == monster->max_hit_points)
{
@@ -2443,7 +2433,7 @@ int mons_ench_f2(monsters *monster, bolt &pbolt)
}
return (MON_AFFECTED);
-} // end mons_ench_f2()
+}
// degree is ignored.
static void _slow_monster(monsters *mon, int /* degree */)
@@ -2509,7 +2499,6 @@ bool curare_hits_monster( const bolt &beam, monsters *monster,
kill_category who, int levels )
{
const bool res_poison = mons_res_poison(monster) > 0;
- bool mondied = false;
poison_monster(monster, who, levels, false);
@@ -2524,14 +2513,10 @@ bool curare_hits_monster( const bolt &beam, monsters *monster,
if (hurted)
{
simple_monster_message(monster, " convulses.");
- if ((monster->hit_points -= hurted) < 1)
- {
- _monster_die(monster, beam);
- mondied = true;
- }
+ monster->hurt(beam.agent(), hurted, BEAM_POISON);
}
- if (!mondied)
+ if (monster->alive())
_slow_monster(monster, levels);
}
@@ -2539,7 +2524,7 @@ bool curare_hits_monster( const bolt &beam, monsters *monster,
if (who == KC_YOU)
did_god_conduct( DID_POISON, 5 + random2(3) );
- return (mondied);
+ return (!monster->alive());
}
// Actually poisons a monster (w/ message).
@@ -2702,7 +2687,7 @@ void mimic_alert(monsters *mimic)
static bool _isBouncy(bolt &beam, unsigned char gridtype)
{
- if (beam.name[0] == '0')
+ if (beam.is_enchantment())
return (false);
if (beam.flavour == BEAM_ELECTRICITY && gridtype != DNGN_METAL_WALL)
@@ -3192,7 +3177,7 @@ static int _affect_place_clouds(bolt &beam, const coord_def& p)
}
// now exit (all enchantments)
- if (beam.name[0] == '0')
+ if (beam.is_enchantment())
return (0);
int clouty = env.cgrid(p);
@@ -3436,7 +3421,7 @@ static std::string _beam_zapper(const bolt &beam)
static bool _beam_is_harmless(bolt &beam, monsters *mon)
{
// For enchantments, this is already handled in _nasty_beam().
- if (beam.name[0] == '0')
+ if (beam.is_enchantment())
return (!_nasty_beam(mon, beam));
// The others are handled here.
@@ -3486,7 +3471,7 @@ static bool _beam_is_harmless_player(bolt &beam)
// Shouldn't happen anyway since enchantments are either aimed at self
// (not prompted) or cast at monsters and don't explode or bounce.
- if (beam.name[0] == '0')
+ if (beam.is_enchantment())
return (false);
// The others are handled here.
@@ -3589,7 +3574,7 @@ static int _affect_player( bolt &beam, item_def *item )
if (you.invisible() && !beam.can_see_invis)
beamHit /= 2;
- if (beam.name[0] != '0')
+ if (!beam.is_enchantment())
{
if (!beam.is_explosion && !beam.aimed_at_feet)
{
@@ -3851,7 +3836,7 @@ static int _affect_player( bolt &beam, item_def *item )
if (beam.aux_source.empty())
beam.aux_source = "by nerve-wracking pain";
- _beam_ouch(roll_dice(beam.damage), beam);
+ _beam_ouch(beam.damage.roll(), beam);
beam.obvious_effect = true;
break;
@@ -3877,7 +3862,7 @@ static int _affect_player( bolt &beam, item_def *item )
beam.damage.size /= 3;
}
}
- _beam_ouch(roll_dice(beam.damage), beam);
+ _beam_ouch(beam.damage.roll(), beam);
beam.obvious_effect = true;
break;
@@ -3887,7 +3872,7 @@ static int _affect_player( bolt &beam, item_def *item )
if (beam.aux_source.empty())
beam.aux_source = "a disintegration bolt";
- _beam_ouch(roll_dice(beam.damage), beam);
+ _beam_ouch(beam.damage.roll(), beam);
beam.obvious_effect = true;
break;
@@ -3947,7 +3932,7 @@ static int _affect_player( bolt &beam, item_def *item )
(beam.is_beam) ? 3 : 2;
// Roll the damage.
- hurted += roll_dice( beam.damage );
+ hurted += beam.damage.roll();
#if DEBUG_DIAGNOSTICS
int roll = hurted;
@@ -4225,13 +4210,12 @@ static int _affect_monster(bolt &beam, monsters *mon, item_def *item)
}
beam.obvious_effect = true;
_update_hurt_or_helped(beam, mon);
- mon->hit_points = 0;
- _monster_die(mon, beam);
+ mon->hurt(beam.agent(), INSTANT_DEATH);
return (BEAM_STOP);
}
bool hit_woke_orc = false;
- if (beam.name[0] == '0') // enchantments
+ if (beam.is_enchantment()) // enchantments: no to-hit check
{
if (beam.is_tracer)
{
@@ -4294,19 +4278,17 @@ static int _affect_monster(bolt &beam, monsters *mon, item_def *item)
enable_attack_conducts(conducts);
- // !@#*( affect_monster_enchantment() has side-effects on
- // the beam structure which screw up range_used_on_hit(),
- // so call it now and store.
- int rangeUsed = _range_used_on_hit(beam);
-
// Doing this here so that the player gets to see monsters
// "flicker and vanish" when turning invisible....
_ench_animation( beam.flavour, mon );
// now do enchantment affect
- int ench_result = _affect_monster_enchantment(beam, mon);
+ mon_resist_type ench_result = _affect_monster_enchantment(beam, mon);
if (mon->alive())
{
+ if (mons_is_mimic(mon->type))
+ mimic_alert(mon);
+
switch (ench_result)
{
case MON_RESIST:
@@ -4325,7 +4307,7 @@ static int _affect_monster(bolt &beam, monsters *mon, item_def *item)
if (hit_woke_orc)
beogh_follower_convert(mon, true);
- return (rangeUsed);
+ return (_range_used_on_hit(beam));
// END non-tracer enchantment
}
@@ -4339,7 +4321,7 @@ static int _affect_monster(bolt &beam, monsters *mon, item_def *item)
// we decide if it actually hits.
// Roll the damage:
- hurt = roll_dice( beam.damage );
+ hurt = beam.damage.roll();
// Water absorbs some of the damage for submerged monsters.
if (submerged)
@@ -4571,19 +4553,12 @@ static int _affect_monster(bolt &beam, monsters *mon, item_def *item)
}
// Now hurt monster.
- hurt_monster( mon, hurt_final );
+ mon->hurt(beam.agent(), hurt_final, beam.flavour);
- if (mon->hit_points < 1)
- {
- _monster_die(mon, beam);
- }
- else
+ if (mon->alive())
{
if (thrower == KILL_YOU_MISSILE && mons_near(mon))
- {
- const monsters *mons = static_cast<const monsters*>(mon);
- print_wounds(mons);
- }
+ print_wounds(mon);
// Don't annoy friendlies or good neutrals if the player's beam
// did no damage. Hostiles will still take umbrage.
@@ -4655,107 +4630,130 @@ static int _affect_monster(bolt &beam, monsters *mon, item_def *item)
return (_range_used_on_hit(beam));
}
-static int _affect_monster_enchantment(bolt &beam, monsters *mon)
+bool _beam_has_saving_throw(const bolt& beam)
{
- bool death_check = false;
+ if (beam.aimed_at_feet)
+ return (false);
+
+ bool rc = true;
- if (beam.flavour == BEAM_TELEPORT) // teleportation
+ switch (beam.flavour)
{
- if (check_mons_resist_magic( mon, beam.ench_power )
- && !beam.aimed_at_feet)
- {
- return (mons_immune_magic(mon) ? MON_UNAFFECTED : MON_RESIST);
- }
+ case BEAM_HASTE:
+ case BEAM_HEALING:
+ case BEAM_INVISIBILITY:
+ case BEAM_DISPEL_UNDEAD:
+ case BEAM_ENSLAVE_DEMON: // it has a different saving throw
+ rc = false;
+ break;
+ default:
+ break;
+ }
+ return rc;
+}
- if (mons_near(mon) && player_monster_visible(mon))
- beam.obvious_effect = true;
+bool _ench_flavour_affects_monster(beam_type flavour, const monsters* mon)
+{
+ bool rc = true;
+ switch (flavour)
+ {
+ case BEAM_POLYMORPH:
+ rc = mon->can_mutate();
+ break;
- monster_teleport(mon, false);
+ case BEAM_DEGENERATE:
+ rc = (mons_holiness(mon) == MH_NATURAL
+ && mon->type != MONS_PULSATING_LUMP);
+ break;
- return (MON_AFFECTED);
- }
+ case BEAM_ENSLAVE_UNDEAD:
+ rc = (mons_holiness(mon) == MH_UNDEAD && mon->attitude != ATT_FRIENDLY);
+ break;
- if (beam.flavour == BEAM_BLINK)
- {
- if (!beam.aimed_at_feet
- && check_mons_resist_magic( mon, beam.ench_power ))
- {
- return mons_immune_magic(mon) ? MON_UNAFFECTED : MON_RESIST;
- }
+ case BEAM_DISPEL_UNDEAD:
+ rc = (mons_holiness(mon) == MH_UNDEAD);
+ break;
- if (mons_near( mon ) && player_monster_visible( mon ))
- beam.obvious_effect = true;
+ case BEAM_ENSLAVE_DEMON:
+ rc = (mons_holiness(mon) == MH_DEMONIC && !mons_friendly(mon));
+ break;
- monster_blink( mon );
- return (MON_AFFECTED);
+ case BEAM_PAIN:
+ rc = !mons_res_negative_energy(mon);
+ break;
+
+ case BEAM_SLEEP:
+ rc = !mon->has_ench(ENCH_SLEEP_WARY) // slept recently
+ && mons_holiness(mon) == MH_NATURAL // no unnatural
+ && mons_res_cold(mon) <= 0; // can't be hibernated
+ break;
+
+ default:
+ break;
}
+
+ return rc;
+}
- if (beam.flavour == BEAM_POLYMORPH)
+static mon_resist_type _affect_monster_enchantment(bolt &beam, monsters *mon)
+{
+ // Early out if the enchantment is meaningless.
+ if (!_ench_flavour_affects_monster(beam.flavour, mon))
+ return (MON_UNAFFECTED);
+
+ // Check magic resistance.
+ if (_beam_has_saving_throw(beam))
{
- if (!mon->can_mutate())
+ if (mons_immune_magic(mon))
return (MON_UNAFFECTED);
+ if (check_mons_resist_magic(mon, beam.ench_power))
+ return (MON_RESIST);
+ }
- if (check_mons_resist_magic( mon, beam.ench_power ))
- return (mons_immune_magic(mon) ? MON_UNAFFECTED : MON_RESIST);
-
+ switch (beam.flavour)
+ {
+ case BEAM_TELEPORT:
+ if (you.can_see(mon))
+ beam.obvious_effect = true;
+ monster_teleport(mon, false);
+ return (MON_AFFECTED);
+
+ case BEAM_BLINK:
+ if (you.can_see(mon))
+ beam.obvious_effect = true;
+ monster_blink(mon);
+ return (MON_AFFECTED);
+
+ case BEAM_POLYMORPH:
if (mon->mutate())
beam.obvious_effect = true;
-
if (YOU_KILL(beam.thrower))
{
did_god_conduct(DID_DELIBERATE_MUTATING, 2 + random2(3),
beam.effect_known);
}
-
return (MON_AFFECTED);
- }
-
- if (beam.flavour == BEAM_BANISH)
- {
- if (check_mons_resist_magic( mon, beam.ench_power ))
- return mons_immune_magic(mon) ? MON_UNAFFECTED : MON_RESIST;
+ case BEAM_BANISH:
if (you.level_type == LEVEL_ABYSS)
simple_monster_message(mon, " wobbles for a moment.");
else
- _monster_die(mon, beam);
-
+ mon->banish();
beam.obvious_effect = true;
return (MON_AFFECTED);
- }
-
- if (beam.flavour == BEAM_DEGENERATE)
- {
- if (mons_holiness(mon) != MH_NATURAL
- || mon->type == MONS_PULSATING_LUMP)
- {
- return (MON_UNAFFECTED);
- }
-
- if (check_mons_resist_magic( mon, beam.ench_power ))
- return mons_immune_magic(mon) ? MON_UNAFFECTED : MON_RESIST;
+ case BEAM_DEGENERATE:
if (monster_polymorph(mon, MONS_PULSATING_LUMP))
beam.obvious_effect = true;
-
return (MON_AFFECTED);
- }
-
- if (beam.flavour == BEAM_DISPEL_UNDEAD)
- {
- if (mons_holiness(mon) != MH_UNDEAD)
- return (MON_UNAFFECTED);
+ case BEAM_DISPEL_UNDEAD:
if (simple_monster_message(mon, " convulses!"))
beam.obvious_effect = true;
+ mon->hurt(beam.agent(), beam.damage.roll());
+ return (MON_AFFECTED);
- hurt_monster( mon, roll_dice( beam.damage ) );
-
- death_check = true;
- }
-
- if (beam.flavour == BEAM_ENSLAVE_UNDEAD
- && mons_holiness(mon) == MH_UNDEAD)
+ case BEAM_ENSLAVE_UNDEAD:
{
const god_type god =
(crawl_state.is_god_acting()) ? crawl_state.which_god_acting()
@@ -4766,12 +4764,6 @@ static int _affect_monster_enchantment(bolt &beam, monsters *mon)
"HD: %d; pow: %d", mon->hit_dice, beam.ench_power);
#endif
- if (mon->attitude == ATT_FRIENDLY)
- return (MON_UNAFFECTED);
-
- if (check_mons_resist_magic(mon, beam.ench_power))
- return mons_immune_magic(mon) ? MON_UNAFFECTED : MON_RESIST;
-
beam.obvious_effect = true;
if (player_will_anger_monster(mon))
{
@@ -4790,9 +4782,7 @@ static int _affect_monster_enchantment(bolt &beam, monsters *mon)
return (MON_AFFECTED);
}
- if (beam.flavour == BEAM_ENSLAVE_DEMON
- && mons_holiness(mon) == MH_DEMONIC)
- {
+ case BEAM_ENSLAVE_DEMON:
#if DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS,
"HD: %d; pow: %d", mon->hit_dice, beam.ench_power );
@@ -4804,10 +4794,6 @@ static int _affect_monster_enchantment(bolt &beam, monsters *mon)
return (MON_RESIST);
}
- // Already friendly.
- if (mons_friendly(mon))
- return (MON_UNAFFECTED);
-
beam.obvious_effect = true;
if (player_will_anger_monster(mon))
{
@@ -4817,116 +4803,47 @@ static int _affect_monster_enchantment(bolt &beam, monsters *mon)
simple_monster_message(mon, " is enslaved.");
- // Wow, permanent enslaving!
+ // Wow, permanent enslaving! (sometimes)
if (one_chance_in(2 + mon->hit_dice / 4))
mon->attitude = ATT_FRIENDLY;
else
mon->add_ench(ENCH_CHARM);
behaviour_event(mon, ME_ALERT, MHITNOT);
-
return (MON_AFFECTED);
- }
-
- //
- // Everything past this point must pass this magic resistance test.
- //
- // Using check_mons_resist_magic here since things like disintegrate
- // are beyond this point. -- bwr
-
- // death_check should be set true already if one of the beams above
- // did its thing but wants to see if the monster died.
- //
- if (!death_check
- && check_mons_resist_magic( mon, beam.ench_power )
- && beam.flavour != BEAM_HASTE
- && beam.flavour != BEAM_HEALING
- && beam.flavour != BEAM_INVISIBILITY)
- {
- return mons_immune_magic(mon) ? MON_UNAFFECTED : MON_RESIST;
- }
-
- if (beam.flavour == BEAM_PAIN) /* pain/agony */
- {
- if (mons_res_negative_energy( mon ))
- return (MON_UNAFFECTED);
+ case BEAM_PAIN: // pain/agony
if (simple_monster_message(mon, " convulses in agony!"))
beam.obvious_effect = true;
- if (beam.name.find("agony") != std::string::npos)
- {
- // AGONY
- mon->hit_points = mon->hit_points / 2;
-
- if (mon->hit_points < 1)
- mon->hit_points = 1;
- }
- else
- {
- // PAIN
- hurt_monster( mon, roll_dice( beam.damage ) );
- }
-
- death_check = true;
- }
+ if (beam.name.find("agony") != std::string::npos) // agony
+ mon->hit_points = std::max(mon->hit_points/2, 1);
+ else // pain
+ mon->hurt(beam.agent(), beam.damage.roll(), beam.flavour);
+ return (MON_AFFECTED);
- if (beam.flavour == BEAM_DISINTEGRATION) /* disrupt/disintegrate */
- {
+ case BEAM_DISINTEGRATION: // disrupt/disintegrate
if (simple_monster_message(mon, " is blasted."))
beam.obvious_effect = true;
-
- hurt_monster( mon, roll_dice( beam.damage ) );
-
- death_check = true;
- }
-
-
- if (beam.flavour == BEAM_SLEEP)
- {
- if (mon->has_ench(ENCH_SLEEP_WARY)) // slept recently
- return (MON_RESIST);
-
- if (mons_holiness(mon) != MH_NATURAL) // no unnatural
- return (MON_UNAFFECTED);
-
- // Cold res monsters resist hibernation (for consistency
- // with mass sleep).
- if (mons_res_cold(mon) > 0)
- return (MON_UNAFFECTED);
-
+ mon->hurt(beam.agent(), beam.damage.roll(), beam.flavour);
+ return (MON_AFFECTED);
+
+ case BEAM_SLEEP:
if (simple_monster_message(mon, " looks drowsy..."))
beam.obvious_effect = true;
-
mon->put_to_sleep();
-
return (MON_AFFECTED);
- }
- if (beam.flavour == BEAM_BACKLIGHT)
- {
+ case BEAM_BACKLIGHT:
if (backlight_monsters(mon->pos(), beam.hit, 0))
{
beam.obvious_effect = true;
return (MON_AFFECTED);
}
return (MON_UNAFFECTED);
- }
- // Everything else?
- if (!death_check)
+ default:
return (mons_ench_f2(mon, beam));
-
- if (mon->hit_points < 1)
- _monster_die(mon, beam);
- else
- {
- print_wounds(mon);
-
- if (mons_is_mimic( mon->type ))
- mimic_alert(mon);
}
-
- return (MON_AFFECTED);
}
@@ -4938,7 +4855,7 @@ static int _range_used_on_hit(bolt &beam)
return (BEAM_STOP);
// CHECK ENCHANTMENTS
- if (beam.name[0] == '0')
+ if (beam.is_enchantment())
{
switch(beam.flavour)
{
@@ -5454,10 +5371,10 @@ static void _explosion_map( bolt &beam, const coord_def& p,
// Only enchantments should need the actual monster type
// to determine this; non-enchantments are pretty
// straightforward.
-static bool _nasty_beam(monsters *mon, bolt &beam)
+static bool _nasty_beam(monsters *mon, const bolt &beam)
{
// Take care of non-enchantments.
- if (beam.name[0] != '0')
+ if (!beam.is_enchantment())
return (true);
// Now for some non-hurtful enchantments.
@@ -5496,7 +5413,7 @@ static bool _nasty_beam(monsters *mon, bolt &beam)
return (true);
}
-static bool _nice_beam(monsters *mon, bolt &beam)
+static bool _nice_beam(monsters *mon, const bolt &beam)
{
// haste/healing/invisibility
if (beam.flavour == BEAM_HASTE || beam.flavour == BEAM_HEALING
@@ -5523,8 +5440,8 @@ bolt::bolt() : range(0), type('*'),
ench_power(0), hit(0),
thrower(KILL_MISC), ex_size(0), beam_source(MHITNOT), name(),
is_beam(false), is_explosion(false), is_big_cloud(false),
- is_enchant(false), is_energy(false), is_launched(false),
- is_thrown(false), target_first(false), aimed_at_spot(false),
+// is_launched(false),
+ aimed_at_spot(false),
aux_source(), affects_nothing(false), obvious_effect(false),
effect_known(true), fr_count(0), foe_count(0), fr_power(0),
foe_power(0), fr_hurt(0), foe_hurt(0), fr_helped(0),
@@ -5585,3 +5502,19 @@ void bolt::setup_retrace()
affects_nothing = true;
aimed_at_spot = true;
}
+
+actor* bolt::agent() const
+{
+ if (YOU_KILL(this->thrower))
+ return (&you);
+ else if (this->beam_source != NON_MONSTER)
+ return (&menv[this->beam_source]);
+ else
+ return (NULL);
+}
+
+bool bolt::is_enchantment() const
+{
+ return (this->flavour >= BEAM_FIRST_ENCHANTMENT
+ && this->flavour <= BEAM_LAST_ENCHANTMENT);
+}
diff --git a/crawl-ref/source/beam.h b/crawl-ref/source/beam.h
index 1806c7ac9f..ec42152515 100644
--- a/crawl-ref/source/beam.h
+++ b/crawl-ref/source/beam.h
@@ -18,12 +18,20 @@ class monsters;
enum demon_beam_type
{
- DMNBM_HELLFIRE, // 0
+ 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
+};
+
// must match wand subtypes! (see item_def::zap())
enum zap_type
{
@@ -115,11 +123,6 @@ struct bolt
bool is_beam; // beams? (can hits multiple targets?)
bool is_explosion;
bool is_big_cloud; // expands into big_cloud at endpoint
- bool is_enchant; // no block/dodge, but mag resist
- bool is_energy; // mostly energy/non-physical attack
- bool is_launched; // was fired from launcher?
- bool is_thrown; // was thrown from hand?
- bool target_first; // targeting by direction
bool aimed_at_spot; // aimed at (x,y), should not cross
std::string aux_source; // source of KILL_MISC beams
@@ -151,38 +154,31 @@ struct bolt
ray_def ray; // shoot on this specific ray
+
public:
// A constructor to try and fix some of the bugs that occur because
// this struct never seems to be properly initialized. Definition
// is over in beam.cc.
bolt();
+ bool is_enchantment() const; // no block/dodge, but mag resist
void set_target(const dist &);
void setup_retrace();
// Returns YOU_KILL or MON_KILL, depending on the source of the beam.
killer_type killer() const;
+
+ actor* agent() const;
};
void sticky_flame_player();
-
void sticky_flame_monster(int mn, kill_category who, int hurt_final);
-
dice_def calc_dice( int num_dice, int max_damage );
// Test if the to-hit (attack) beats evasion (defence).
bool test_beam_hit(int attack, int defence);
-
-/* ***********************************************************************
- * called from: bang - it_use2 - monstuff - mstuff2
- * *********************************************************************** */
void fire_beam(bolt &pbolt, item_def *item = NULL, bool drop_item = false);
-// last updated 12may2000 {dlb}
-/* ***********************************************************************
- * called from: ability - it_use3 - item_use - mstuff2 - religion -
- * spells - spells4
- * *********************************************************************** */
int explosion( bolt &pbolt, bool hole_in_the_middle = false,
bool explode_in_wall = false,
bool stop_at_statues = true,
@@ -190,58 +186,30 @@ int explosion( bolt &pbolt, bool hole_in_the_middle = false,
bool show_more = true,
bool affect_items = true);
-// last updated 22jan2001 {gdl}
-/* ***********************************************************************
- * called from: effects - spells2 - spells4
- * *********************************************************************** */
int mons_adjust_flavoured(monsters *monster, bolt &pbolt, int hurted,
bool doFlavouredEffects = true);
-/* ***********************************************************************
- * called from: ability - item_use - spell
- * returns true if messages were generated during the enchantment
- * *********************************************************************** */
+// returns 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 );
-/* ***********************************************************************
- * called from: fight - monstuff - mstuff2
- * *********************************************************************** */
-int mons_ench_f2( monsters *monster, struct bolt &pbolt );
+mon_resist_type mons_ench_f2(monsters *monster, bolt &pbolt);
-/* ***********************************************************************
- * called from: fight - monstuff - spells2
- * *********************************************************************** */
bool poison_monster( monsters *monster, kill_category who,
int levels = 1, bool force = false, bool verbose = true );
-
-
-/* ***********************************************************************
- * called from: monstuff
- * *********************************************************************** */
void fire_tracer( const monsters *monster, struct bolt &pbolt,
bool explode_only = false );
-
bool check_line_of_sight( const coord_def& source, const coord_def& target );
-
-/* ***********************************************************************
- * called from: monstuff
- * *********************************************************************** */
void mimic_alert( monsters *mimic );
-
-
bool zapping( zap_type ztype, int power, struct bolt &pbolt,
bool needs_tracer = false, std::string msg = "" );
-
bool player_tracer( zap_type ztype, int power, struct bolt &pbolt,
int range = 0 );
-
int affect(bolt &beam, const coord_def& p, item_def *item = NULL,
bool affect_items = true);
-
void beam_drop_object( bolt &beam, item_def *item, const coord_def& where );
#endif
diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc
index 582270242a..a785592378 100644
--- a/crawl-ref/source/effects.cc
+++ b/crawl-ref/source/effects.cc
@@ -113,47 +113,38 @@ int holy_word_monsters(coord_def where, int pow, int caster)
retval = holy_word_player(pow, caster);
// Is a monster in this cell?
- int mon = mgrd(where);
+ const int mon = mgrd(where);
if (mon == NON_MONSTER)
return retval;
monsters *monster = &menv[mon];
- if (invalid_monster(monster) || !mons_is_unholy(monster)
+ if (!monster->alive()
+ || !mons_is_unholy(monster)
|| (is_good_god(you.religion)
&& (is_follower(monster) || mons_neutral(monster))))
{
return retval;
}
- int hploss = std::max(0, roll_dice(2, 15) + (random2(pow) / 3));
+ const int hploss = roll_dice(2, 15) + (random2(pow) / 3);
+ retval = 1;
// Currently, holy word annoys the monsters it affects because it
// can kill them, and because hostile monsters don't use it.
behaviour_event(monster, ME_ANNOY, MHITYOU);
simple_monster_message(monster, " convulses!");
- hurt_monster(monster, hploss);
-
- if (hploss)
+ monster->hurt(&you, hploss);
+
+ if (monster->alive())
{
- retval = 1;
- if (!monster->alive())
- {
- monster_die(monster, KILL_YOU, NON_MONSTER);
- return retval;
- }
- }
+ if (monster->speed_increment >= 25)
+ monster->speed_increment -= 20;
- if (monster->speed_increment >= 25)
- {
- retval = 1;
- monster->speed_increment -= 20;
+ monster->add_ench(ENCH_FEAR);
}
- if (monster->add_ench(ENCH_FEAR))
- retval = 1;
-
return retval;
}
@@ -247,7 +238,7 @@ int torment_monsters(coord_def where, int pow, int caster)
monsters *monster = &menv[mon];
- if (invalid_monster(monster) || mons_res_negative_energy(monster) == 3)
+ if (!monster->alive() || mons_res_negative_energy(monster) == 3)
return retval;
int hploss = std::max(0, monster->hit_points / 2 - 1);
@@ -260,10 +251,7 @@ int torment_monsters(coord_def where, int pow, int caster)
{
retval = 1;
if (!monster->alive())
- {
- monster_die(monster, KILL_YOU, NON_MONSTER);
return retval;
- }
}
simple_monster_message(monster, " convulses!");
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index dca549073d..64c48819e6 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -175,68 +175,70 @@ enum quiver_type
enum beam_type // beam[].flavour
{
- BEAM_NONE, // 0
+ BEAM_NONE,
BEAM_MISSILE,
BEAM_MMISSILE, // and similarly irresistible things
BEAM_FIRE,
BEAM_COLD,
- BEAM_MAGIC, // 5
+ BEAM_MAGIC,
BEAM_ELECTRICITY,
BEAM_POISON,
BEAM_NEG,
BEAM_ACID,
- BEAM_MIASMA, // 10
+ BEAM_MIASMA,
BEAM_SPORE,
BEAM_POISON_ARROW,
BEAM_HELLFIRE,
BEAM_NAPALM,
- BEAM_STEAM, // 15
+ BEAM_STEAM,
BEAM_HELLFROST,
BEAM_ENERGY,
- BEAM_HOLY, // aka beam of cleansing, golden flame
+ BEAM_HOLY,
BEAM_FRAG,
- BEAM_LAVA, // 20
+ BEAM_LAVA,
BEAM_BACKLIGHT,
BEAM_SLEEP,
BEAM_ICE,
BEAM_NUKE,
BEAM_RANDOM, // 25 - currently translates into FIRE..ACID
- // These used to be handled in the colour field:
- BEAM_SLOW, // BLACK
- BEAM_HASTE, // BLUE
- BEAM_HEALING, // GREEN
- BEAM_PARALYSIS, // CYAN
- BEAM_CONFUSION, // RED - 30
- BEAM_INVISIBILITY, // MAGENTA
- BEAM_DIGGING, // BROWN
- BEAM_TELEPORT, // LIGHTGREY
- BEAM_POLYMORPH, // DARKGREY
- BEAM_CHARM, // LIGHTBLUE - 35
- BEAM_BANISH, // LIGHTGREEN
- BEAM_DEGENERATE, // LIGHTCYAN
- BEAM_ENSLAVE_UNDEAD, // LIGHTRED
- BEAM_PAIN, // LIGHTMAGENTA
- BEAM_DISPEL_UNDEAD, // YELLOW - 40
- BEAM_DISINTEGRATION, // WHITE
- BEAM_ENSLAVE_DEMON, // colour "16"
+ // Enchantments
+ BEAM_FIRST_ENCHANTMENT,
+ BEAM_SLOW = BEAM_FIRST_ENCHANTMENT,
+ BEAM_HASTE,
+ BEAM_HEALING,
+ BEAM_PARALYSIS,
+ BEAM_CONFUSION,
+ BEAM_INVISIBILITY,
+ BEAM_DIGGING,
+ BEAM_TELEPORT,
+ BEAM_POLYMORPH,
+ BEAM_CHARM,
+ BEAM_BANISH,
+ BEAM_DEGENERATE,
+ BEAM_ENSLAVE_UNDEAD,
+ BEAM_PAIN,
+ BEAM_DISPEL_UNDEAD,
+ BEAM_DISINTEGRATION,
+ BEAM_ENSLAVE_DEMON,
BEAM_BLINK,
BEAM_PETRIFY,
+ BEAM_LAST_ENCHANTMENT = BEAM_PETRIFY,
// new beams for evaporate
- BEAM_POTION_STINKING_CLOUD, // 45
+ BEAM_POTION_STINKING_CLOUD,
BEAM_POTION_POISON,
BEAM_POTION_MIASMA,
BEAM_POTION_STEAM,
BEAM_POTION_FIRE,
- BEAM_POTION_COLD, // 50
+ BEAM_POTION_COLD,
BEAM_POTION_BLACK_SMOKE,
BEAM_POTION_GREY_SMOKE,
BEAM_POTION_BLUE_SMOKE,
BEAM_POTION_PURP_SMOKE,
- BEAM_POTION_RANDOM, // 55
+ BEAM_POTION_RANDOM,
BEAM_TORMENT_DAMAGE, // Pseudo-beam for damage flavour.
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 6214570cd7..184f366e61 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -303,7 +303,8 @@ public:
virtual bool can_safely_mutate() const = 0;
virtual bool mutate() = 0;
virtual int hurt(const actor *attacker, int amount,
- beam_type flavour = BEAM_MISSILE) = 0;
+ beam_type flavour = BEAM_MISSILE,
+ bool cleanup_dead = true) = 0;
virtual void heal(int amount, bool max_too = false) = 0;
virtual void banish(const std::string &who = "") = 0;
virtual void blink(bool allow_partial_control = true) = 0;
@@ -404,6 +405,7 @@ struct dice_def
int size;
dice_def( int n = 0, int s = 0 ) : num(n), size(s) {}
+ int roll() const;
};
struct run_check_dir
@@ -892,7 +894,8 @@ public:
void rot(actor *agent, int rotlevel, int immed_rot);
void heal(int amount, bool max_too = false);
int hurt(const actor *attacker, int amount,
- beam_type flavour = BEAM_MISSILE);
+ beam_type flavour = BEAM_MISSILE,
+ bool cleanup_dead = true);
int holy_aura() const;
int warding() const;
@@ -1292,7 +1295,8 @@ public:
void confuse(int strength);
void rot(actor *agent, int rotlevel, int immed_rot);
int hurt(const actor *attacker, int amount,
- beam_type flavour = BEAM_MISSILE);
+ beam_type flavour = BEAM_MISSILE,
+ bool cleanup_dead = true);
void heal(int amount, bool max_too = false);
void blink(bool allow_partial_control = true);
void teleport(bool right_now = false, bool abyss_shift = false);
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 8e1d8623bc..a4268f015b 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -1189,7 +1189,7 @@ bool melee_attack::player_apply_aux_unarmed()
stab_bonus = 0;
aux_damage = player_apply_monster_ac(aux_damage);
- aux_damage = hurt_monster(def, aux_damage);
+ aux_damage = def->hurt(&you, aux_damage, BEAM_MISSILE, false);
damage_done = aux_damage;
if (damage_done > 0)
@@ -1221,12 +1221,9 @@ bool melee_attack::player_apply_aux_unarmed()
}
if (def->hit_points < 1)
- {
monster_die(def, KILL_YOU, NON_MONSTER);
- return (true);
- }
- return (false);
+ return (!def->alive());
}
std::string melee_attack::debug_damage_number()
@@ -1722,7 +1719,8 @@ int melee_attack::player_weapon_type_modify(int damage)
bool melee_attack::player_hurt_monster()
{
- return damage_done && (damage_done = hurt_monster(def, damage_done));
+ return damage_done && (damage_done = def->hurt(&you, damage_done,
+ BEAM_MISSILE, false));
}
void melee_attack::player_exercise_combat_skills()
@@ -1852,15 +1850,9 @@ bool melee_attack::player_monattk_hit_effects(bool mondied)
special_damage);
#endif
- special_damage = hurt_monster(def, special_damage);
+ special_damage = def->hurt(&you, special_damage);
- if (def->hit_points < 1)
- {
- monster_die(def, KILL_YOU, NON_MONSTER);
- return (true);
- }
-
- return (false);
+ return (!def->alive());
}
static bool is_boolean_resist(beam_type flavour)
diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc
index f20a518928..992bb6a5ad 100644
--- a/crawl-ref/source/items.cc
+++ b/crawl-ref/source/items.cc
@@ -364,10 +364,6 @@ void unlink_item( int dest )
mitm[dest].pos.reset();
mitm[dest].link = NON_ITEM;
-
- // This causes problems when changing levels. -- bwr
- // if (monster->type == MONS_DANCING_WEAPON)
- // monster_die(monster, KILL_RESET, NON_MONSTER);
return;
}
}
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 2ca6d2addc..123d8a5511 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -4951,9 +4951,12 @@ god_type monsters::deity() const
return (god);
}
-int monsters::hurt(const actor *agent, int amount, beam_type flavour)
+int monsters::hurt(const actor *agent, int amount, beam_type flavour,
+ bool cleanup_dead)
{
- if (amount <= 0)
+ if (amount == INSTANT_DEATH)
+ amount = hit_points;
+ else if (amount <= 0)
return (0);
amount = std::min(amount, hit_points);
@@ -4962,9 +4965,11 @@ int monsters::hurt(const actor *agent, int amount, beam_type flavour)
// Allow the victim to exhibit passive damage behaviour (royal jelly).
react_to_damage(amount, flavour);
- if (agent && (hit_points < 1 || hit_dice < 1) && type != -1)
+ if (cleanup_dead && (hit_points < 1 || hit_dice < 1) && type != -1)
{
- if (agent->atype() == ACT_PLAYER)
+ if (agent == NULL)
+ monster_die(this, KILL_MISC, NON_MONSTER);
+ else if (agent->atype() == ACT_PLAYER)
monster_die(this, KILL_YOU, NON_MONSTER);
else
{
@@ -6136,7 +6141,9 @@ void monsters::apply_enchantment(const mon_enchant &me)
if (dam > 0)
{
- hurt_monster(this, dam);
+ // We don't have a reasonable agent to give.
+ // Don't clean up the monster in order to credit properly.
+ this->hurt(NULL, dam, BEAM_POISON, false);
#if DEBUG_DIAGNOSTICS
// For debugging, we don't have this silent.
@@ -6145,6 +6152,7 @@ void monsters::apply_enchantment(const mon_enchant &me)
mprf(MSGCH_DIAGNOSTICS, "poison damage: %d", dam );
#endif
+ // Credit the kill.
if (hit_points < 1)
{
monster_die(this, me.killer(), me.kill_agent());
@@ -6159,7 +6167,7 @@ void monsters::apply_enchantment(const mon_enchant &me)
{
if (hit_points > 1 && one_chance_in(3))
{
- hurt_monster(this, 1);
+ this->hurt(NULL, 1); // nonlethal so we don't care about agent
if (hit_points < max_hit_points && coinflip())
--max_hit_points;
}
@@ -6171,19 +6179,21 @@ void monsters::apply_enchantment(const mon_enchant &me)
// Assumption: mons_res_fire has already been checked.
case ENCH_STICKY_FLAME:
{
- int dam =
- resist_adjust_damage(this, BEAM_FIRE, res_fire(),
- roll_dice( 2, 4 ) - 1);
+ int dam = resist_adjust_damage(this, BEAM_FIRE, res_fire(),
+ roll_dice(2, 4) - 1);
if (dam > 0)
{
- hurt_monster(this, dam);
simple_monster_message(this, " burns!");
+ // We don't have a reasonable agent to give.
+ // Don't clean up the monster in order to credit properly.
+ this->hurt(NULL, dam, BEAM_NAPALM, false);
#if DEBUG_DIAGNOSTICS
mprf( MSGCH_DIAGNOSTICS, "sticky flame damage: %d", dam );
#endif
+ // Credit the kill.
if (hit_points < 1)
{
monster_die(this, me.killer(), me.kill_agent());
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index f2549cd11d..caa77f743d 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -1968,15 +1968,9 @@ void mons_get_damage_level( const monsters* monster, std::string& desc,
void print_wounds(const monsters *monster)
{
- if (monster->type == -1)
+ if (!monster->alive() || monster->hit_points == monster->max_hit_points)
return;
- if (monster->hit_points == monster->max_hit_points
- || monster->hit_points < 1)
- {
- return;
- }
-
if (monster_descriptor(monster->type, MDSC_NOMSG_WOUNDS))
return;
@@ -7398,15 +7392,13 @@ static void _mons_in_cloud(monsters *monster)
behaviour_event(monster, ME_DISTURB, MHITNOT, monster->pos());
}
- hurted = std::max(0, hurted);
-
if (hurted > 0)
{
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "%s takes %d damage from cloud.",
monster->name(DESC_CAP_THE).c_str(), hurted);
#endif
- hurt_monster(monster, hurted);
+ monster->hurt(NULL, hurted, BEAM_MISSILE, false);
if (monster->hit_points < 1)
{
diff --git a/crawl-ref/source/monstuff.h b/crawl-ref/source/monstuff.h
index ee76711d2e..21b58c7126 100644
--- a/crawl-ref/source/monstuff.h
+++ b/crawl-ref/source/monstuff.h
@@ -183,7 +183,8 @@ bool message_current_target(void);
unsigned int monster_index(const monsters *monster);
-void mons_get_damage_level(const monsters*, std::string& desc, mon_dam_level_type&);
+void mons_get_damage_level(const monsters*, std::string& desc,
+ mon_dam_level_type&);
int hurt_monster(monsters *victim, int damage_dealt);
diff --git a/crawl-ref/source/mstuff2.cc b/crawl-ref/source/mstuff2.cc
index 773e4433cf..7d827de14c 100644
--- a/crawl-ref/source/mstuff2.cc
+++ b/crawl-ref/source/mstuff2.cc
@@ -1819,7 +1819,6 @@ bolt mons_spells( monsters *mons, spell_type spell_cast, int power )
beam.flavour = BEAM_BLINK;
beam.thrower = KILL_MON;
beam.is_beam = true;
- beam.is_enchant = true;
break;
default:
diff --git a/crawl-ref/source/ouch.cc b/crawl-ref/source/ouch.cc
index 120b0f316f..6fb5819f63 100644
--- a/crawl-ref/source/ouch.cc
+++ b/crawl-ref/source/ouch.cc
@@ -804,11 +804,9 @@ static void _yred_mirrors_injury(int dam, int death_source)
flash_monster_colour(mon, RED, 200);
#endif
- hurt_monster(mon, dam);
+ mon->hurt(&you, dam);
- if (mon->hit_points < 1)
- monster_die(mon, KILL_YOU, NON_MONSTER);
- else
+ if (mon->alive())
print_wounds(mon);
lose_piety(integer_sqrt(dam));
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index ebd6b2d28b..c0d0cf39e0 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -6450,8 +6450,10 @@ void player::teleport(bool now, bool abyss_shift)
you_teleport();
}
-int player::hurt(const actor *agent, int amount, beam_type flavour)
+int player::hurt(const actor *agent, int amount, beam_type flavour,
+ bool cleanup_dead)
{
+ // We ignore cleanup_dead here.
const monsters *mon = dynamic_cast<const monsters*>(agent);
if (agent->atype() == ACT_MONSTER)
{
diff --git a/crawl-ref/source/spells2.cc b/crawl-ref/source/spells2.cc
index f181ab51b5..35f0257eee 100644
--- a/crawl-ref/source/spells2.cc
+++ b/crawl-ref/source/spells2.cc
@@ -640,7 +640,7 @@ void cast_refrigeration(int pow)
// Handle the player.
const dice_def dam_dice(3, 5 + pow / 10);
- const int hurted = check_your_resists(roll_dice( dam_dice ), BEAM_COLD);
+ const int hurted = check_your_resists(dam_dice.roll(), BEAM_COLD);
if (hurted > 0)
{
@@ -694,15 +694,16 @@ void cast_refrigeration(int pow)
if (monster->alive() && mons_near(monster))
{
// Calculate damage and apply.
- int hurt = mons_adjust_flavoured(monster,beam,roll_dice(dam_dice));
- if (hurt > 0)
- hurt_monster(monster, hurt);
-
- // Kill monster if necessary; cold-blooded creatures can be slowed.
- if (monster->hit_points < 1)
- monster_die(monster, KILL_YOU, NON_MONSTER);
- else if (mons_class_flag(monster->type, M_COLD_BLOOD) && coinflip())
+ int hurt = mons_adjust_flavoured(monster, beam, dam_dice.roll());
+ monster->hurt(&you, hurt, BEAM_COLD);
+
+ // Cold-blooded creatures can be slowed.
+ if (monster->alive()
+ && mons_class_flag(monster->type, M_COLD_BLOOD)
+ && coinflip())
+ {
monster->add_ench(ENCH_SLOW);
+ }
}
}
}
@@ -743,12 +744,10 @@ void drain_life(int pow)
const int hurted = 3 + random2(7) + random2(pow);
behaviour_event(monster, ME_WHACK, MHITYOU, you.pos());
- hurt_monster(monster, hurted);
hp_gain += hurted;
- if (monster->hit_points < 1)
- monster_die(monster, KILL_YOU, NON_MONSTER);
- else
+ monster->hurt(&you, hurted);
+ if (monster->alive())
print_wounds(monster);
}
}
@@ -805,15 +804,13 @@ bool vampiric_drain(int pow, const dist &vmove)
return (false);
}
- hurt_monster(monster, inflicted);
-
mprf("You feel life coursing from %s into your body!",
monster->name(DESC_NOCAP_THE).c_str());
- print_wounds(monster);
+ monster->hurt(&you, inflicted);
- if (monster->hit_points < 1)
- monster_die(monster, KILL_YOU, NON_MONSTER);
+ if (monster->alive())
+ print_wounds(monster);
inc_hp(inflicted / 2, false);
diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc
index 9cb7ac7434..a968f7de85 100644
--- a/crawl-ref/source/spells3.cc
+++ b/crawl-ref/source/spells3.cc
@@ -221,11 +221,8 @@ int cast_smiting(int power, dist &beam)
// Maxes out at around 40 damage at 27 Invocations, which is
// plenty in my book (the old max damage was around 70,
// which seems excessive).
- hurt_monster(monster, 7 + (random2(power) * 33 / 191));
-
- if (monster->hit_points < 1)
- monster_die(monster, KILL_YOU, NON_MONSTER);
- else
+ monster->hurt(&you, 7 + (random2(power) * 33 / 191));
+ if (monster->alive())
print_wounds(monster);
}
}
@@ -278,11 +275,8 @@ int airstrike(int power, dist &beam)
if (hurted < 0)
hurted = 0;
- hurt_monster(monster, hurted);
-
- if (monster->hit_points < 1)
- monster_die(monster, KILL_YOU, NON_MONSTER);
- else
+ monster->hurt(&you, hurted);
+ if (monster->alive())
print_wounds(monster);
}
}
diff --git a/crawl-ref/source/spells4.cc b/crawl-ref/source/spells4.cc
index c7e2b572c2..10fc85342c 100644
--- a/crawl-ref/source/spells4.cc
+++ b/crawl-ref/source/spells4.cc
@@ -74,24 +74,16 @@ void do_monster_rot(int mon);
inline bool player_hurt_monster(int monster, int damage)
{
ASSERT( monster != NON_MONSTER );
+ monsters& m = menv[monster];
if (damage > 0)
{
- hurt_monster( &menv[monster], damage );
-
- if (menv[monster].hit_points > 0)
- {
- const monsters *mons = static_cast<const monsters*>(&menv[monster]);
- print_wounds(mons);
- }
- else
- {
- monster_die(&menv[monster], KILL_YOU, NON_MONSTER);
- return (true);
- }
+ m.hurt(&you, damage);
+ if (m.alive())
+ print_wounds(&m);
}
- return (false);
+ return (!m.alive());
}
// Here begin the actual spells:
@@ -180,7 +172,7 @@ static int _shatter_monsters(coord_def where, int pow, int garbage)
break;
}
- int damage = roll_dice( dam_dice ) - random2( menv[monster].ac );
+ int damage = dam_dice.roll() - random2( menv[monster].ac );
if (damage > 0)
player_hurt_monster( monster, damage );
@@ -592,7 +584,7 @@ static int _ignite_poison_monsters(coord_def where, int pow, int garbage)
// (although only one should actually be present at a given time).
dam_dice.num += strength;
- int damage = roll_dice( dam_dice );
+ int damage = dam_dice.roll();
if (damage > 0)
{
damage = mons_adjust_flavoured( mon, beam, damage );
@@ -1742,7 +1734,7 @@ bool cast_fragmentation(int pow, const dist& spd)
beam.colour = WHITE;
beam.damage.num = 2;
beam.flavour = BEAM_ICE;
- if (player_hurt_monster(midx, roll_dice(beam.damage)))
+ if (player_hurt_monster(midx, beam.damage.roll()))
beam.damage.num++;
break;
@@ -1766,7 +1758,7 @@ bool cast_fragmentation(int pow, const dist& spd)
else
{
beam.damage.num = 2;
- if (player_hurt_monster(midx, roll_dice(beam.damage)))
+ if (player_hurt_monster(midx, beam.damage.roll()))
beam.damage.num += 2;
}
goto all_done; // i.e. no "Foo Explodes!"
@@ -1779,7 +1771,7 @@ bool cast_fragmentation(int pow, const dist& spd)
// fizzle (since we don't actually explode wood golems). -- bwr
explode = false;
beam.damage.num = 2;
- player_hurt_monster(midx, roll_dice(beam.damage));
+ player_hurt_monster(midx, beam.damage.roll());
break;
case MONS_IRON_GOLEM:
@@ -1788,7 +1780,7 @@ bool cast_fragmentation(int pow, const dist& spd)
beam.name = "blast of metal fragments";
beam.colour = CYAN;
beam.damage.num = 4;
- if (player_hurt_monster(midx, roll_dice(beam.damage)))
+ if (player_hurt_monster(midx, beam.damage.roll()))
beam.damage.num += 2;
break;
@@ -1801,7 +1793,7 @@ bool cast_fragmentation(int pow, const dist& spd)
beam.name = "blast of rock fragments";
beam.colour = BROWN;
beam.damage.num = 3;
- if (player_hurt_monster(midx, roll_dice(beam.damage)))
+ if (player_hurt_monster(midx, beam.damage.roll()))
beam.damage.num++;
break;
@@ -1823,7 +1815,7 @@ bool cast_fragmentation(int pow, const dist& spd)
}
{
- int statue_damage = roll_dice(beam.damage) * 2;
+ int statue_damage = beam.damage.roll() * 2;
if (pow >= 50 && one_chance_in(10))
statue_damage = mon->hit_points;
@@ -1838,7 +1830,7 @@ bool cast_fragmentation(int pow, const dist& spd)
beam.name = "blast of crystal shards";
beam.colour = WHITE;
beam.damage.num = 4;
- if (player_hurt_monster(midx, roll_dice(beam.damage)))
+ if (player_hurt_monster(midx, beam.damage.roll()))
beam.damage.num += 2;
break;
@@ -1855,7 +1847,7 @@ bool cast_fragmentation(int pow, const dist& spd)
beam.name = "blast of petrified fragments";
beam.colour = mon->colour;
beam.damage.num = petrifying ? 2 : 3;
- if (player_hurt_monster(midx, roll_dice(beam.damage)))
+ if (player_hurt_monster(midx, beam.damage.roll()))
beam.damage.num++;
break;
}
@@ -2237,13 +2229,9 @@ void cast_far_strike(int pow)
}
// Inflict the damage.
- hurt_monster( monster, damage );
- if (monster->hit_points < 1)
- monster_die(monster, KILL_YOU, NON_MONSTER);
- else
- print_wounds( monster );
-
- return;
+ monster->hurt(&you, damage);
+ if (monster->alive())
+ print_wounds(monster);
}
int cast_apportation(int pow)
diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc
index a0274b61d5..7a55036f2c 100644
--- a/crawl-ref/source/spl-cast.cc
+++ b/crawl-ref/source/spl-cast.cc
@@ -2575,9 +2575,8 @@ void MiscastEffect::_ouch(int dam, beam_type flavour)
beem.flavour = flavour;
dam = mons_adjust_flavoured(mon_target, beem, dam, true);
- hurt_monster(mon_target, dam);
-
- if (mon_target->hit_points < 1)
+ mon_target->hurt(NULL, dam, BEAM_MISSILE, false);
+ if (!mon_target->alive())
monster_die(mon_target, kt, kill_source);
}
else
diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc
index 36124b4e70..2b78d546c8 100644
--- a/crawl-ref/source/stuff.cc
+++ b/crawl-ref/source/stuff.cc
@@ -650,11 +650,6 @@ int roll_dice( int num, int size )
return (ret);
}
-int roll_dice( const struct dice_def &dice )
-{
- return (roll_dice( dice.num, dice.size ));
-}
-
// originally designed to randomize evasion -
// values are slightly lowered near (max) and
// approach an upper limit somewhere near (limit/2)
@@ -1673,3 +1668,8 @@ int random_rod_subtype()
{
return STAFF_SMITING + random2(NUM_STAVES - STAFF_SMITING);
}
+
+int dice_def::roll() const
+{
+ return roll_dice(this->num, this->size);
+}
diff --git a/crawl-ref/source/stuff.h b/crawl-ref/source/stuff.h
index 3c6818776c..7682bd2fe5 100644
--- a/crawl-ref/source/stuff.h
+++ b/crawl-ref/source/stuff.h
@@ -40,10 +40,8 @@ int random2avg( int max, int rolls );
int bestroll(int max, int rolls);
int roll_dice( int num, int size );
-int roll_dice( const struct dice_def &dice );
void scale_dice( dice_def &dice, int threshold = 24 );
-
// Various ways to iterate over things.
// stack_iterator guarantees validity so long as you don't manually
diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc
index b69a514fd4..a66b9fb40f 100644
--- a/crawl-ref/source/traps.cc
+++ b/crawl-ref/source/traps.cc
@@ -471,9 +471,9 @@ void trap_def::trigger(actor& triggerer, bool flat_footed)
if (!mons_is_summoned(m))
bleed_onto_floor(m->pos(), m->type, damage_taken, true);
- hurt_monster(m, damage_taken);
- if (m->hit_points < 1)
- monster_die(m, KILL_MISC, NON_MONSTER);
+ m->hurt(NULL, damage_taken);
+ if (in_sight && m->alive())
+ print_wounds(m);
}
}
break;
@@ -1203,9 +1203,7 @@ void trap_def::shoot_ammo(actor& act, bool was_known)
poison_monster(monster, KC_OTHER);
// Apply damage.
- hurt_monster(monster, damage_taken);
- if (monster->hit_points < 1)
- monster_die(monster, KILL_MISC, NON_MONSTER);
+ monster->hurt(NULL, damage_taken);
}
// Drop the item (sometimes.)