diff options
author | dshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573> | 2007-03-18 07:05:07 +0000 |
---|---|---|
committer | dshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573> | 2007-03-18 07:05:07 +0000 |
commit | 3fdf3ab24ea63ecde6537ea122e2ab1cd6b8d4f1 (patch) | |
tree | a838b57e94a87f84fcdbf3e551b365aec922259d /crawl-ref/source/mtransit.cc | |
parent | de11c27378236139089c48ecfb0b66457cc0d67c (diff) | |
download | crawl-ref-3fdf3ab24ea63ecde6537ea122e2ab1cd6b8d4f1.tar.gz crawl-ref-3fdf3ab24ea63ecde6537ea122e2ab1cd6b8d4f1.zip |
Banished uniques (including ghosts) will now be sent to the Abyss. Banished
non-uniques may also get the Abyss treatment if they clear a HD roll.
Crawl tries very hard not to lose banished monsters, preserving them across
Abyss shifts and teleports, and saving them on the transit list when the player
escapes the Abyss.
Breaks savefile compatibility.
Toned down Vehumet and wizardry boosts a touch.
Fixed bugginess where player could get aux unarmed attacks on a monster that
just teleported away (by weapon of distortion).
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1052 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/mtransit.cc')
-rw-r--r-- | crawl-ref/source/mtransit.cc | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/crawl-ref/source/mtransit.cc b/crawl-ref/source/mtransit.cc new file mode 100644 index 0000000000..bb58f68909 --- /dev/null +++ b/crawl-ref/source/mtransit.cc @@ -0,0 +1,159 @@ +/* + * File: mtransit.cc + * Summary: Tracks monsters that are in suspended animation between levels. + * Written by: Darshan Shaligram + * + * Modified for Crawl Reference by $Author: dshaligram $ on $Date: 2007-03-15T20:10:20.648083Z $ + */ + +#include "AppHdr.h" + +#include "mtransit.h" +#include "items.h" +#include "mon-util.h" +#include "stuff.h" + +#define MAX_LOST 100 + +monsters_in_transit the_lost_ones; + +static void place_lost_monsters(m_transit_list &m); + +static void cull_lost(m_transit_list &mlist, int how_many) +{ + // First pass, drop non-uniques. + m_transit_list::iterator i = mlist.begin(); + + for ( ; i != mlist.end(); ) + { + m_transit_list::iterator finger = i++; + if (!mons_is_unique(finger->mons.type)) + { + mlist.erase(finger); + + if (--how_many <= 0) + return; + } + } + + // If we're still over the limit (unlikely), just lose + // the old ones. + while (how_many-- > MAX_LOST && !mlist.empty()) + mlist.erase( mlist.begin() ); +} + +void add_monster_to_transit(level_id lid, const monsters &m) +{ + m_transit_list &mlist = the_lost_ones[lid]; + mlist.push_back(m); + +#ifdef DEBUG_DIAGNOSTICS + mprf(MSGCH_DIAGNOSTICS, "Monster in transit: %s", + m.name(DESC_PLAIN).c_str()); +#endif + + const int how_many = mlist.size(); + if (how_many > MAX_LOST) + cull_lost(mlist, how_many); +} + +void place_transiting_monsters() +{ + level_id c = level_id::current(); + + monsters_in_transit::iterator i = the_lost_ones.find(c); + if (i == the_lost_ones.end()) + return; + + place_lost_monsters(i->second); + if (i->second.empty()) + the_lost_ones.erase(i); +} + +static bool place_lost_monster(follower &f) +{ + return (f.place(false)); +} + +static void place_lost_monsters(m_transit_list &m) +{ + for (m_transit_list::iterator i = m.begin(); + i != m.end(); ) + { + m_transit_list::iterator mon = i++; + + // Transiting monsters have a 50% chance of being placed. + if (coinflip()) + continue; + + if (place_lost_monster(*mon)) + m.erase(mon); + } +} + +////////////////////////////////////////////////////////////////////////// +// follower + +follower::follower(const monsters &m) : mons(m), items() +{ + load_mons_items(); +} + +void follower::load_mons_items() +{ + for (int i = 0; i < NUM_MONSTER_SLOTS; ++i) + if (mons.inv[i] != NON_ITEM) + items[i] = mitm[ mons.inv[i] ]; + else + items[i].clear(); +} + +bool follower::place(bool near_player) +{ + for (int i = 0; i < MAX_MONSTERS - 5; ++i) + { + monsters &m = menv[i]; + if (m.alive()) + continue; + + m = mons; + if (m.find_place_to_live(near_player)) + { +#ifdef DEBUG_DIAGNOSTICS + mprf(MSGCH_DIAGNOSTICS, "Placed follower: %s", + m.name(DESC_PLAIN).c_str()); +#endif + m.target_x = m.target_y = 0; + m.flags |= MF_JUST_SUMMONED; + + restore_mons_items(m); + return (true); + } + + m.reset(); + break; + } + + return (false); +} + +void follower::restore_mons_items(monsters &m) +{ + for (int i = 0; i < NUM_MONSTER_SLOTS; ++i) + { + if (items[i].base_type == OBJ_UNASSIGNED) + m.inv[i] = NON_ITEM; + else + { + const int islot = get_item_slot(0); + m.inv[i] = islot; + if (islot == NON_ITEM) + continue; + + item_def &it = mitm[islot]; + it = items[i]; + it.x = it.y = 0; + it.link = NON_ITEM; + } + } +} |