diff options
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; + } + } +} |