summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/beam.cc
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-03-21 21:23:21 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-03-21 21:23:21 +0000
commit109b00ddba65e56db1a90a374115df69070bca71 (patch)
tree0d22819524e8d7a5179e7ee280a4b16b16d6ded2 /crawl-ref/source/beam.cc
parent101ce9277219b6925dc9e7c70692984c6544c5cd (diff)
downloadcrawl-ref-109b00ddba65e56db1a90a374115df69070bca71.tar.gz
crawl-ref-109b00ddba65e56db1a90a374115df69070bca71.zip
Cleaned up monster enchantments. Instead of the old enum abuse (ENCH_ABJ_I, II,
etc.), enchantment is stored as a struct (ENCH_which, degree, whose_enchantment). This allows us to do such things as award experience for monsters poisoned by friends, or confused monsters bashing themselves or falling into lava (not implemented, but could be :-)). Doing monster_die() correctly is a little tricky for friendly-enchantment-deaths because the original monster may not be around to answer questions, so we fake the killer's stats for indirect friendly kills (which means that some gods may not award piety for minion-cast enchantments, f'r'instance). I think we can live with that for now. Breaks save file compatibility as usual. Clouds could also use similar treatment - poison clouds created by a friendly are not correctly tracked yet. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1075 c06c8d41-db1a-0410-9941-cceddc491573
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);
}