summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/beam.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/beam.cc')
-rw-r--r--crawl-ref/source/beam.cc191
1 files changed, 64 insertions, 127 deletions
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index 593f6c3cc3..38cca50cd3 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -68,7 +68,7 @@ static FixedArray < bool, 19, 19 > explode_map;
// helper functions (some of these, esp. affect(), should probably
// be public):
-static void sticky_flame_monster( int mn, bool source, int hurt_final );
+static void sticky_flame_monster( int mn, kill_category who, int hurt_final );
static bool affectsWall(const bolt &beam, int wall_feature);
static bool isBouncy(struct bolt &beam, unsigned char gridtype);
static void beam_drop_object( struct bolt &beam, item_def *item, int x, int y );
@@ -126,6 +126,22 @@ 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))
+ return (KC_YOU);
+ else if (MON_KILL(beam.thrower))
+ {
+ if (beam.beam_source >= 0 && beam.beam_source < MAX_MONSTERS)
+ {
+ const monsters &mons = menv[beam.beam_source];
+ if (mons.attitude == ATT_FRIENDLY)
+ return (KC_FRIENDLY);
+ }
+ }
+ return (KC_OTHER);
+}
+
// simple animated flash from Rupert Smith (and expanded to be more generic):
void zap_animation( int colour, const monsters *mon, bool force )
{
@@ -1565,7 +1581,7 @@ int mons_adjust_flavoured( struct monsters *monster, struct bolt &pbolt,
}
else if (doFlavouredEffects && !one_chance_in(3))
{
- poison_monster( monster, YOU_KILL(pbolt.thrower) );
+ poison_monster( monster, whose_kill(pbolt) );
}
break;
@@ -1579,14 +1595,14 @@ int mons_adjust_flavoured( struct monsters *monster, struct bolt &pbolt,
// Poison arrow can poison any living thing regardless of
// poison resistance. -- bwr
if (mons_has_lifeforce(monster))
- poison_monster( monster, YOU_KILL(pbolt.thrower), 2, true );
+ poison_monster( monster, whose_kill(pbolt), 2, true );
}
hurted /= 2;
}
else if (doFlavouredEffects)
{
- poison_monster( monster, YOU_KILL(pbolt.thrower), 4 );
+ poison_monster( monster, whose_kill(pbolt), 4 );
}
break;
@@ -1638,7 +1654,7 @@ int mons_adjust_flavoured( struct monsters *monster, struct bolt &pbolt,
return (hurted);
if (mons_res_poison( monster ) <= 0)
- poison_monster( monster, YOU_KILL(pbolt.thrower) );
+ poison_monster( monster, whose_kill(pbolt) );
if (one_chance_in( 3 + 2 * mons_res_negative_energy(monster) ))
{
@@ -1806,10 +1822,10 @@ bool mass_enchantment( int wh_enchant, int pow, int origin )
continue;
}
- if (mons_has_ench(monster, wh_enchant))
+ if (monster->has_ench(static_cast<enchant_type>(wh_enchant)))
continue;
- if (mons_add_ench(monster, wh_enchant))
+ if (monster->add_ench(static_cast<enchant_type>(wh_enchant)))
{
if (player_monster_visible( monster ))
{
@@ -1860,7 +1876,7 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt)
{
case BEAM_SLOW: /* 0 = slow monster */
// try to remove haste, if monster is hasted
- if (mons_del_ench(monster, ENCH_HASTE))
+ if (monster->del_ench(ENCH_HASTE))
{
if (simple_monster_message(monster, " is no longer moving quickly."))
pbolt.obvious_effect = true;
@@ -1869,9 +1885,9 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt)
}
// not hasted, slow it
- if (!mons_has_ench(monster, ENCH_SLOW)
+ if (!monster->has_ench(ENCH_SLOW)
&& !mons_is_stationary(monster)
- && mons_add_ench(monster, ENCH_SLOW))
+ && monster->add_ench(ENCH_SLOW))
{
if (!mons_is_paralysed(monster)
&& simple_monster_message(monster, " seems to slow down."))
@@ -1882,7 +1898,7 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt)
return (MON_AFFECTED);
case BEAM_HASTE: // 1 = haste
- if (mons_del_ench(monster, ENCH_SLOW))
+ if (monster->del_ench(ENCH_SLOW))
{
if (simple_monster_message(monster, " is no longer moving slowly."))
pbolt.obvious_effect = true;
@@ -1891,9 +1907,9 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt)
}
// not slowed, haste it
- if (!mons_has_ench(monster, ENCH_HASTE)
+ if (!monster->has_ench(ENCH_HASTE)
&& !mons_is_stationary(monster)
- && mons_add_ench(monster, ENCH_HASTE))
+ && monster->add_ench(ENCH_HASTE))
{
if (!mons_is_paralysed(monster)
&& simple_monster_message(monster, " seems to speed up."))
@@ -1925,7 +1941,7 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt)
return (MON_AFFECTED);
case BEAM_CONFUSION: /* 4 = confusion */
- if (mons_add_ench(monster, ENCH_CONFUSION))
+ if (monster->add_ench(ENCH_CONFUSION))
{
// put in an exception for fungi, plants and other things you won't
// notice becoming confused.
@@ -1939,8 +1955,8 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt)
{
const std::string monster_name = ptr_monam(monster, DESC_CAP_THE);
- if (!mons_has_ench(monster, ENCH_INVIS)
- && mons_add_ench(monster, ENCH_INVIS))
+ if (!monster->has_ench(ENCH_INVIS)
+ && monster->add_ench(ENCH_INVIS))
{
// Can't use simple_monster_message here, since it checks
// for visibility of the monster (and its now invisible) -- bwr
@@ -1957,7 +1973,7 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt)
return (MON_AFFECTED);
}
case BEAM_CHARM: /* 9 = charm */
- if (mons_add_ench(monster, ENCH_CHARM))
+ if (monster->add_ench(ENCH_CHARM))
{
// break fleeing and suchlike
monster->behaviour = BEH_SEEK;
@@ -1986,8 +2002,8 @@ static void slow_monster(monsters *mon, int /* degree */)
static void beam_paralyses_monster(bolt &pbolt, monsters *monster)
{
- if (!mons_has_ench(monster, ENCH_PARALYSIS)
- && mons_add_ench(monster, ENCH_PARALYSIS))
+ if (!monster->has_ench(ENCH_PARALYSIS)
+ && monster->add_ench(ENCH_PARALYSIS))
{
if (simple_monster_message(monster, " suddenly stops moving!"))
pbolt.obvious_effect = true;
@@ -1998,14 +2014,14 @@ static void beam_paralyses_monster(bolt &pbolt, monsters *monster)
// Returns true if the curare killed the monster.
bool curare_hits_monster( const bolt &beam,
- monsters *monster,
- bool fromPlayer,
+ monsters *monster,
+ kill_category who,
int levels )
{
const bool res_poison = mons_res_poison(monster);
bool mondied = false;
- poison_monster(monster, fromPlayer, levels, false);
+ poison_monster(monster, who, levels, false);
if (!mons_res_asphyx(monster))
{
@@ -2030,134 +2046,55 @@ bool curare_hits_monster( const bolt &beam,
}
// Deities take notice.
- if (fromPlayer)
+ if (who == KC_YOU)
did_god_conduct( DID_POISON, 5 + random2(3) );
return (mondied);
}
// actually poisons a monster (w/ message)
-void poison_monster( struct monsters *monster, bool fromPlayer, int levels,
+void poison_monster( monsters *monster,
+ kill_category from_whom,
+ int levels,
bool force )
{
- bool yourPoison = false;
- int ench = ENCH_NONE;
- int old_strength = 0;
-
- if (monster->type == -1)
+ if (!monster->alive())
return;
if (!force && mons_res_poison(monster) > 0)
return;
- // who gets the credit if monster dies of poison?
- ench = mons_has_ench( monster, ENCH_POISON_I, ENCH_POISON_IV );
- if (ench != ENCH_NONE)
- {
- old_strength = ench - ENCH_POISON_I;
- }
- else
- {
- ench = mons_has_ench(monster, ENCH_YOUR_POISON_I, ENCH_YOUR_POISON_IV);
- if (ench != ENCH_NONE)
- {
- old_strength = ench - ENCH_YOUR_POISON_I;
- yourPoison = true;
- }
- }
-
- // delete old poison
- mons_del_ench( monster, ENCH_POISON_I, ENCH_POISON_IV, true );
- mons_del_ench( monster, ENCH_YOUR_POISON_I, ENCH_YOUR_POISON_IV, true );
-
- // Calculate new strength:
- int new_strength = old_strength + levels;
- if (new_strength > 3)
- new_strength = 3;
-
- // now, if player poisons the monster at ANY TIME, they should
- // get credit for the kill if the monster dies from poison. This
- // really isn't that abusable -- GDL.
- if (fromPlayer || yourPoison)
- ench = ENCH_YOUR_POISON_I + new_strength;
- else
- ench = ENCH_POISON_I + new_strength;
+ const mon_enchant old_pois = monster->get_ench(ENCH_POISON);
+ monster->add_ench( mon_enchant(ENCH_POISON, levels, from_whom) );
+ const mon_enchant new_pois = monster->get_ench(ENCH_POISON);
// actually do the poisoning
// note: order important here
- if (mons_add_ench( monster, ench ) && new_strength > old_strength)
+ if (new_pois.degree > old_pois.degree)
{
simple_monster_message( monster,
- (old_strength == 0) ? " looks ill."
- : " looks even sicker." );
+ !old_pois.degree? " looks ill."
+ : " looks even sicker." );
}
// finally, take care of deity preferences
- if (fromPlayer)
+ if (from_whom == KC_YOU)
did_god_conduct( DID_POISON, 5 + random2(3) );
} // end poison_monster()
// actually napalms a monster (w/ message)
-void sticky_flame_monster( int mn, bool fromPlayer, int levels )
+void sticky_flame_monster( int mn, kill_category who, int levels )
{
- bool yourFlame = fromPlayer;
- int currentFlame;
- int currentStrength = 0;
+ monsters *monster = &menv[mn];
- struct monsters *monster = &menv[mn];
-
- if (monster->type == -1)
+ if (!monster->alive())
return;
if (mons_res_fire(monster) > 0)
return;
- // who gets the credit if monster dies of napalm?
- currentFlame = mons_has_ench( monster, ENCH_STICKY_FLAME_I,
- ENCH_STICKY_FLAME_IV );
-
- if (currentFlame != ENCH_NONE)
- {
- currentStrength = currentFlame - ENCH_STICKY_FLAME_I;
- yourFlame = false;
- }
- else
- {
- currentFlame = mons_has_ench( monster, ENCH_YOUR_STICKY_FLAME_I,
- ENCH_YOUR_STICKY_FLAME_IV );
-
- if (currentFlame != ENCH_NONE)
- {
- currentStrength = currentFlame - ENCH_YOUR_STICKY_FLAME_I;
- yourFlame = true;
- }
- else
- currentStrength = -1; // no flame yet!
- }
-
- // delete old flame
- mons_del_ench( monster, ENCH_STICKY_FLAME_I, ENCH_STICKY_FLAME_IV, true );
- mons_del_ench( monster, ENCH_YOUR_STICKY_FLAME_I, ENCH_YOUR_STICKY_FLAME_IV,
- true );
-
- // increase sticky flame strength, cap at 3 (level is 0..3)
- currentStrength += levels;
-
- if (currentStrength > 3)
- currentStrength = 3;
-
- // now, if player flames the monster at ANY TIME, they should
- // get credit for the kill if the monster dies from napalm. This
- // really isn't that abusable -- GDL.
- if (fromPlayer || yourFlame)
- currentStrength += ENCH_YOUR_STICKY_FLAME_I;
- else
- currentStrength += ENCH_STICKY_FLAME_I;
-
- // actually do flame
- if (mons_add_ench( monster, currentStrength ))
+ if (monster->add_ench(mon_enchant(ENCH_STICKY_FLAME, levels, who)))
simple_monster_message(monster, " is covered in liquid fire!");
-
} // end sticky_flame_monster
/*
@@ -2229,7 +2166,7 @@ bool check_line_of_sight( int sx, int sy, int tx, int ty )
*/
void mimic_alert(monsters *mimic)
{
- if (mons_has_ench( mimic, ENCH_TP_I, ENCH_TP_IV ))
+ if (mimic->has_ench(ENCH_TP))
return;
monster_teleport( mimic, !one_chance_in(3) );
@@ -2492,7 +2429,7 @@ int affect(struct bolt &beam, int x, int y)
// if there is a monster at this location, affect it
// submerged monsters aren't really there -- bwr
int mid = mgrd[x][y];
- if (mid != NON_MONSTER && !mons_has_ench( &menv[mid], ENCH_SUBMERGED ))
+ if (mid != NON_MONSTER && !menv[mid].has_ench( ENCH_SUBMERGED ))
{
if (!beam.is_big_cloud
&& (!beam.is_explosion || beam.in_explosion_phase))
@@ -3381,7 +3318,7 @@ static int affect_monster(struct bolt &beam, struct monsters *mon)
if (beam.is_tracer)
{
// check can see other monster
- if (!beam.can_see_invis && mons_has_ench(&menv[tid], ENCH_INVIS))
+ if (!beam.can_see_invis && menv[tid].has_ench(ENCH_INVIS))
{
// can't see this monster, ignore it
return 0;
@@ -3482,7 +3419,7 @@ static int affect_monster(struct bolt &beam, struct monsters *mon)
// BEGIN non-enchantment (could still be tracer)
- if (mons_has_ench( mon, ENCH_SUBMERGED ) && !beam.aimed_at_feet)
+ if (mon->has_ench(ENCH_SUBMERGED) && !beam.aimed_at_feet)
return (0); // missed me!
// we need to know how much the monster _would_ be hurt by this, before
@@ -3638,7 +3575,7 @@ static int affect_monster(struct bolt &beam, struct monsters *mon)
if (levels > 4)
levels = 4;
- sticky_flame_monster( tid, YOU_KILL(beam.thrower), levels );
+ sticky_flame_monster( tid, whose_kill(beam), levels );
}
@@ -3652,18 +3589,18 @@ static int affect_monster(struct bolt &beam, struct monsters *mon)
if (beam.ench_power == AUTOMATIC_HIT
&& random2(100) < 90 - (3 * mon->ac))
{
- poison_monster( mon, YOU_KILL(beam.thrower), 2 );
+ poison_monster( mon, whose_kill(beam), 2 );
}
else if (random2(hurt_final) - random2(mon->ac) > 0)
{
- poison_monster( mon, YOU_KILL(beam.thrower) );
+ poison_monster( mon, whose_kill(beam) );
}
}
bool wake_mimic = true;
if (beam.name.find("curare") != std::string::npos)
{
- if (curare_hits_monster( beam, mon, YOU_KILL(beam.thrower), 2 ))
+ if (curare_hits_monster( beam, mon, whose_kill(beam), 2 ))
wake_mimic = false;
}
@@ -3863,7 +3800,7 @@ static int affect_monster_enchantment(struct bolt &beam, struct monsters *mon)
if (beam.flavour == BEAM_SLEEP)
{
- if (mons_has_ench( mon, ENCH_SLEEP_WARY )) // slept recently
+ if (mon->has_ench(ENCH_SLEEP_WARY)) // slept recently
return (MON_RESIST);
if (mons_holiness(mon) != MH_NATURAL) // no unnatural
@@ -3873,7 +3810,7 @@ static int affect_monster_enchantment(struct bolt &beam, struct monsters *mon)
beam.obvious_effect = true;
mon->behaviour = BEH_SLEEP;
- mons_add_ench( mon, ENCH_SLEEP_WARY );
+ mon->add_ench(ENCH_SLEEP_WARY);
return (MON_AFFECTED);
}