diff options
author | dolorous <dolorous@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-06-17 18:30:45 +0000 |
---|---|---|
committer | dolorous <dolorous@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-06-17 18:30:45 +0000 |
commit | 94410e34844eacecadec9c0f3b8e96b2833d16e6 (patch) | |
tree | 801d9dfbafb11f404ac732d304923b74a9ed1141 | |
parent | 73466105efd4afd0b5317668be0109395e931659 (diff) | |
download | crawl-ref-94410e34844eacecadec9c0f3b8e96b2833d16e6.tar.gz crawl-ref-94410e34844eacecadec9c0f3b8e96b2833d16e6.zip |
Add an unfinished attempt at making pacified monsters leave the level.
BEH_LEAVE replaces BEH_INVESTIGATE, which wasn't being used.
Notes:
Since leaving the level is similar to fleeing in some ways, monsters
leaving the level share some behaviors with fleeing monsters: they are
less likely to shoot; they are more likely to use scrolls of blinking or
teleportation; and leaving eyeballs won't paralyze you or drain your MP.
Leaving the level is also similar to lurking in some ways, so it won't
be interrupted by noticing something, just as with lurking.
Getting far enough away from a monster will make it leave the level
(i.e., die with KILL_DISMISSED and MF_HARD_RESET, so it takes its stuff
with it), as will getting it into a grid it can submerge in, at which
time it will submerge and leave the level. Neither of these apply to
monsters that can't move, of course, except for mimics, since they can
teleport.
Incomplete things (sorry for the mess):
I still haven't figured out how to make a monster target a dungeon
feature (in this case, the nearest level exit, the nearest teleportation
or shaft trap, or the nearest submersible grid), so, currently, a
pacified monster will just go to where its last target was and stand
there until/unless one of the aforementioned level exit scenarios
occurs.
Pacified monsters can still cast summoning spells. Whatever they summon
is neutral, just as they are, but such summons can still get in the way.
(Try pacifying an orc high priest, for example.) Maybe summoning should
be disabled or have its chance lowered for neutral monsters in general,
unless something's in their way?
Speaking of targeting, the leaving-by-submerging scenario should occur
only if there's no other way to reach the target: all ways off the level
are blocked, the monster's habitat is water and it's not amphibious, the
monster's habitat is lava, or (possibly) the monster's habitat is rock.
There should be a message if the monster leaves the level, but what
about the ones that do so out of the player's LOS?
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5924 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r-- | crawl-ref/source/debug.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/enum.h | 2 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.cc | 20 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.h | 3 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 103 |
5 files changed, 101 insertions, 29 deletions
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc index 8296d9e22b..6b51f2ae84 100644 --- a/crawl-ref/source/debug.cc +++ b/crawl-ref/source/debug.cc @@ -1768,7 +1768,7 @@ void debug_stethoscope(int mon) (menv[i].behaviour == BEH_FLEE) ? "flee" : (menv[i].behaviour == BEH_CORNERED) ? "cornered" : (menv[i].behaviour == BEH_PANIC) ? "panic" : - (menv[i].behaviour == BEH_INVESTIGATE) ? "investigate" : + (menv[i].behaviour == BEH_LEAVE) ? "leave" : (menv[i].behaviour == BEH_LURK) ? "lurk" : "unknown"), menv[i].behaviour, diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index abd9e474ee..14581e94a0 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -1872,7 +1872,7 @@ enum beh_type BEH_FLEE, BEH_CORNERED, BEH_PANIC, // like flee but without running away - BEH_INVESTIGATE, // investigating an ME_DISTURB + BEH_LEAVE, // leave the level BEH_LURK, // stay still until discovered or // enemy close by NUM_BEHAVIOURS, // max # of legal states diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index bc4877f425..ae7ac4af5c 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -425,6 +425,13 @@ bool mons_is_stationary(const monsters *mon) return mons_class_is_stationary(mon->type); } +// Mimics can teleport, so they're not truly stationary. +// XXX: There should be a more generic way to check for this! +bool mons_is_truly_stationary(const monsters *mon) +{ + return (mons_is_stationary(mon) && !mons_is_mimic(mon->type)); +} + bool mons_is_insubstantial(int mc) { return mons_class_flag(mc, M_INSUBSTANTIAL); @@ -2105,6 +2112,11 @@ bool mons_good_neutral(const monsters *m) return (m->attitude == ATT_GOOD_NEUTRAL); } +bool mons_is_pacified(const monsters *m) +{ + return (m->attitude == ATT_NEUTRAL && testbits(m->flags, MF_GOT_HALF_XP)); +} + bool mons_wont_attack(const monsters *m) { return (mons_friendly(m) || mons_good_neutral(m)); @@ -2200,6 +2212,11 @@ bool mons_is_cornered(const monsters *m) return (m->behaviour == BEH_CORNERED); } +bool mons_is_leaving(const monsters *m) +{ + return (m->behaviour == BEH_LEAVE); +} + bool mons_is_lurking(const monsters *m) { return (m->behaviour == BEH_LURK); @@ -2252,6 +2269,9 @@ void mons_pacify(monsters *mon) gain_exp(exper_value(mon) / 2 + 1, &exp_gain, &avail_gain); mon->flags |= MF_GOT_HALF_XP; } + + // Make the monster leave the level. + behaviour_event(mon, ME_EVAL); } bool mons_should_fire(struct bolt &beam) diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h index 7914e5f360..7b00dee43e 100644 --- a/crawl-ref/source/mon-util.h +++ b/crawl-ref/source/mon-util.h @@ -639,6 +639,7 @@ size_type mons_size(const monsters *m); bool mons_friendly(const monsters *m); bool mons_neutral(const monsters *m); bool mons_good_neutral(const monsters *m); +bool mons_is_pacified(const monsters *m); bool mons_wont_attack(const monsters *m); bool mons_att_wont_attack(mon_attitude_type fr); mon_attitude_type mons_attitude(const monsters *m); @@ -657,6 +658,7 @@ bool mons_is_seeking(const monsters *m); bool mons_is_fleeing(const monsters *m); bool mons_is_panicking(const monsters *m); bool mons_is_cornered(const monsters *m); +bool mons_is_leaving(const monsters *m); bool mons_is_lurking(const monsters *m); bool mons_is_batty(const monsters *m); bool mons_was_seen(const monsters *m); @@ -681,6 +683,7 @@ bool mons_class_is_confusable(int mc); bool mons_class_is_slowable(int mc); bool mons_class_is_stationary(int mc); bool mons_is_stationary(const monsters *mon); +bool mons_is_truly_stationary(const monsters *mon); bool mons_is_wall_shielded(int mc); bool mons_is_insubstantial(int mc); bool mons_has_blood(int mc); diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index f18aa3dc23..ae1f19aa65 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -2147,27 +2147,24 @@ void behaviour_event(monsters *mon, int event, int src, // Do any resultant foe or state changes. _handle_behaviour(mon); - if (old_behaviour == BEH_LURK && !mons_is_lurking(mon)) - { - switch(event) - { - case ME_EVAL: - case ME_DISTURB: - case ME_ALERT: - // Lurking monsters won't stop lurking just because they - // noticed something. - mon->behaviour = BEH_LURK; - break; + const bool wasLurking = + (old_behaviour == BEH_LURK && !mons_is_lurking(mon)); + const bool wasLeaving = + (old_behaviour == BEH_LEAVE && !mons_is_leaving(mon)); - default: - if (mon->has_ench(ENCH_SUBMERGED) - && !mon->del_ench(ENCH_SUBMERGED)) - { - // Lurking monsters that can't unsubmerge keep lurking. - mon->behaviour = BEH_LURK; - } - break; - } + if ((wasLurking || wasLeaving) + && (event == ME_DISTURB || event == ME_ALERT || event == ME_EVAL)) + { + // Lurking monsters or monsters leaving the level won't stop + // doing so just because they noticed something. + mon->behaviour = old_behaviour; + } + else if (wasLurking && mon->has_ench(ENCH_SUBMERGED) + && !mon->del_ench(ENCH_SUBMERGED)) + { + // The same goes for lurking submerged monsters, if they can't + // unsubmerge. + mon->behaviour = BEH_LURK; } } @@ -2408,6 +2405,16 @@ static void _mark_neighbours_player_unreachable(monsters *mon) } } +static void _make_mons_leave_level(monsters *mon) +{ + if (mons_is_leaving(mon)) + { + // Monsters leaving the level take their stuff with them. + mon->flags |= MF_HARD_RESET; + monster_die(mon, KILL_DISMISSED, 0); + } +} + //--------------------------------------------------------------- // // handle_behaviour @@ -2941,6 +2948,14 @@ static void _handle_behaviour(monsters *mon) break; case BEH_WANDER: + // Monsters that have been pacified leave the level. + if (mons_is_pacified(mon)) + { + new_foe = MHITNOT; + new_beh = BEH_LEAVE; + break; + } + // Is our foe in LOS? // Batty monsters don't automatically reseek so that // they'll flitter away, we'll reset them just before @@ -3200,6 +3215,31 @@ static void _handle_behaviour(monsters *mon) } break; + case BEH_LEAVE: + // If the monster can't move at all (or even teleport, as a + // mimic would), it obviously can't leave, so get out. + if (mons_is_truly_stationary(mon)) + break; + + // If the monster can submerge where it is, make it do so + // and leave the level. + if (monster_can_submerge(mon, grd(mon->pos()))) + { + mon->add_ench(ENCH_SUBMERGED); + _make_mons_leave_level(mon); + return; + } + + // If the monster is far enough away from the player, make + // it leave the level. + if (distance(mon->x, mon->y, you.x_pos, you.y_pos) + >= LOS_RADIUS * LOS_RADIUS * 4) + { + _make_mons_leave_level(mon); + return; + } + break; + case BEH_FLEE: // Check for healed. if (isHealthy && !isScared) @@ -3673,7 +3713,8 @@ static void _handle_nearby_ability(monsters *monster) case MONS_GIANT_EYEBALL: if (coinflip() && !mons_friendly(monster) && !mons_is_wandering(monster) - && !mons_is_fleeing(monster)) + && !mons_is_fleeing(monster) + && !mons_is_leaving(monster)) { simple_monster_message(monster, " stares at you."); @@ -3686,7 +3727,8 @@ static void _handle_nearby_ability(monsters *monster) case MONS_EYE_OF_DRAINING: if (coinflip() && !mons_friendly(monster) && !mons_is_wandering(monster) - && !mons_is_fleeing(monster)) + && !mons_is_fleeing(monster) + && !mons_is_leaving(monster)) { simple_monster_message(monster, " stares at you."); @@ -4135,9 +4177,10 @@ static bool _handle_special_ability(monsters *monster, bolt & beem) } // Won't sing if either of you silenced, or it's friendly, - // confused or fleeing. + // confused, fleeing, or leaving the level. if (monster->has_ench(ENCH_CONFUSION) || mons_is_fleeing(monster) + || mons_is_leaving(monster) || mons_friendly(monster) || silenced(monster->x, monster->y) || silenced(you.x_pos, you.y_pos)) @@ -4441,7 +4484,8 @@ static bool _handle_scroll(monsters *monster) case SCR_TELEPORTATION: if (!monster->has_ench(ENCH_TP)) { - if (mons_is_fleeing(monster) || mons_is_caught(monster)) + if (mons_is_fleeing(monster) || mons_is_leaving(monster) + || mons_is_caught(monster)) { simple_monster_message(monster, " reads a scroll."); monster_teleport(monster, false); @@ -4452,7 +4496,8 @@ static bool _handle_scroll(monsters *monster) break; case SCR_BLINKING: - if (mons_is_fleeing(monster) || mons_is_caught(monster)) + if (mons_is_fleeing(monster) || mons_is_leaving(monster) + || mons_is_caught(monster)) { if (mons_near(monster)) { @@ -5353,9 +5398,13 @@ static bool _handle_throw(monsters *monster, bolt & beem) return (false); } - // Greatly lowered chances if the monster is fleeing. - if (mons_is_fleeing(monster) && !one_chance_in(8)) + // Greatly lowered chances if the monster is fleeing or leaving the + // level. + if ((mons_is_fleeing(monster) || mons_is_leaving(monster)) + && !one_chance_in(8)) + { return (false); + } item_def *launcher = NULL; const item_def *weapon = NULL; |