summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/mtransit.cc
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2007-12-03 06:54:53 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2007-12-03 06:54:53 +0000
commit38e77f4ea4395ed90f12e880224e5bd378113602 (patch)
tree87a0ca74f0fc77d59a32fd1317f739cf9ddb1530 /crawl-ref/source/mtransit.cc
parentcca6195c042a64fed711dba3ea0d94bc78b410df (diff)
downloadcrawl-ref-38e77f4ea4395ed90f12e880224e5bd378113602.tar.gz
crawl-ref-38e77f4ea4395ed90f12e880224e5bd378113602.zip
Items can now fall through shaft traps (trap doors). The code is rather
simplistic, and it's not currently possible to make a "baited" shaft; also, there is no threshold weight, so even a single dart will open up (and thus reveal) a shaft trap. Breaks savefile compatibility. Monsters which fall through a shaft now show up 100% of the time on the player's next visit to the shaft's destination level. Also, the monster is placed close to the spot where the player would end up if s/he went through the same shaft. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@2988 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/mtransit.cc')
-rw-r--r--crawl-ref/source/mtransit.cc144
1 files changed, 137 insertions, 7 deletions
diff --git a/crawl-ref/source/mtransit.cc b/crawl-ref/source/mtransit.cc
index 8361f015bd..20c5510bc1 100644
--- a/crawl-ref/source/mtransit.cc
+++ b/crawl-ref/source/mtransit.cc
@@ -7,20 +7,25 @@
*/
#include "AppHdr.h"
-
#include "mtransit.h"
+
+#include "dungeon.h"
#include "items.h"
+#include "monplace.h"
#include "mon-util.h"
+#include "monstuff.h"
+#include "randart.h"
#include "stuff.h"
#define MAX_LOST 100
monsters_in_transit the_lost_ones;
+items_in_transit transiting_items;
static void level_place_lost_monsters(m_transit_list &m);
static void level_place_followers(m_transit_list &m);
-static void cull_lost(m_transit_list &mlist, int how_many)
+static void cull_lost_mons(m_transit_list &mlist, int how_many)
{
// First pass, drop non-uniques.
for (m_transit_list::iterator i = mlist.begin(); i != mlist.end(); )
@@ -41,6 +46,53 @@ static void cull_lost(m_transit_list &mlist, int how_many)
mlist.erase( mlist.begin() );
}
+static void cull_lost_items(i_transit_list &ilist, int how_many)
+{
+ // First pass, drop non-artifacts.
+ for (i_transit_list::iterator i = ilist.begin(); i != ilist.end(); )
+ {
+ i_transit_list::iterator finger = i++;
+ if (!is_artefact(*finger))
+ {
+ ilist.erase(finger);
+
+ if (--how_many <= MAX_LOST)
+ return;
+ }
+ }
+
+ // Second pass, drop randarts.
+ for (i_transit_list::iterator i = ilist.begin(); i != ilist.end(); )
+ {
+ i_transit_list::iterator finger = i++;
+ if (is_random_artefact(*finger))
+ {
+ ilist.erase(finger);
+
+ if (--how_many <= MAX_LOST)
+ return;
+ }
+ }
+
+ // Third pass, drop unrandarts.
+ for (i_transit_list::iterator i = ilist.begin(); i != ilist.end(); )
+ {
+ i_transit_list::iterator finger = i++;
+ if (is_unrandom_artefact(*finger))
+ {
+ ilist.erase(finger);
+
+ if (--how_many <= MAX_LOST)
+ return;
+ }
+ }
+
+ // If we're still over the limit (unlikely), just lose
+ // the old ones.
+ while (how_many-- > MAX_LOST && !ilist.empty())
+ ilist.erase( ilist.begin() );
+}
+
m_transit_list *get_transit_list(const level_id &lid)
{
monsters_in_transit::iterator i = the_lost_ones.find(lid);
@@ -59,7 +111,7 @@ void add_monster_to_transit(const level_id &lid, const monsters &m)
const int how_many = mlist.size();
if (how_many > MAX_LOST)
- cull_lost(mlist, how_many);
+ cull_lost_mons(mlist, how_many);
}
void place_lost_ones(void (*placefn)(m_transit_list &ml))
@@ -100,8 +152,9 @@ static void level_place_lost_monsters(m_transit_list &m)
{
m_transit_list::iterator mon = i++;
- // Transiting monsters have a 50% chance of being placed.
- if (coinflip())
+ // Monsters transiting to the Abyss have a 50% chance of being
+ // placed, otherwise a 100% chance.
+ if (you.level_type == LEVEL_ABYSS && coinflip())
continue;
if (place_lost_monster(*mon))
@@ -120,6 +173,55 @@ static void level_place_followers(m_transit_list &m)
}
}
+void add_item_to_transit(const level_id &lid, const item_def &i)
+{
+ i_transit_list &ilist = transiting_items[lid];
+ ilist.push_back(i);
+
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Item in transit: %s",
+ i.name(DESC_PLAIN).c_str());
+#endif
+
+ const int how_many = ilist.size();
+ if (how_many > MAX_LOST)
+ cull_lost_items(ilist, how_many);
+}
+
+void place_transiting_items()
+{
+ level_id c = level_id::current();
+
+ items_in_transit::iterator i = transiting_items.find(c);
+ if (i == transiting_items.end())
+ return;
+
+ i_transit_list &ilist = i->second;
+ i_transit_list keep;
+ i_transit_list::iterator item;
+
+ for (item = ilist.begin(); item != ilist.end(); item++)
+ {
+ coord_def pos(item->x, item->y);
+
+ if (!in_bounds(pos))
+ {
+ pos.x = random_range(X_BOUND_1 + 1, X_BOUND_2 - 1);
+ pos.y = random_range(Y_BOUND_1 + 1, Y_BOUND_2 - 1);
+ }
+
+ const coord_def where_to_go =
+ dgn_find_nearby_stair(DNGN_ROCK_STAIRS_DOWN, pos, true);
+
+ // List of items we couldn't place
+ if (!copy_item_to_grid(*item, where_to_go.x, where_to_go.y))
+ keep.push_back(*item);
+ }
+
+ // Only unplaceable items are kept in list.
+ ilist = keep;
+}
+
//////////////////////////////////////////////////////////////////////////
// follower
@@ -141,12 +243,40 @@ bool follower::place(bool near_player)
{
for (int i = 0; i < MAX_MONSTERS - 5; ++i)
{
+ // Find first empty slot in menv and copy monster into it.
monsters &m = menv[i];
if (m.alive())
continue;
-
m = mons;
- if (m.find_place_to_live(near_player))
+
+ bool placed = false;
+
+ // In certain instances (currently, falling through a shaft)
+ // try to place monster a close as possible to its previous
+ // <x,y> coordinates.
+ if (!near_player && you.level_type == LEVEL_DUNGEON
+ && in_bounds(m.pos()))
+ {
+ const coord_def where_to_go =
+ dgn_find_nearby_stair(DNGN_ROCK_STAIRS_DOWN,
+ m.pos(), true);
+
+ if (monster_habitable_grid(&m, grd(where_to_go)))
+ {
+ if (where_to_go == you.pos())
+ near_player = true;
+ else
+ {
+ mgrd[where_to_go.x][where_to_go.y] = monster_index(&m);
+ placed = true;
+ }
+ }
+ }
+
+ if (!placed)
+ placed = m.find_place_to_live(near_player);
+
+ if (placed)
{
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "Placed follower: %s",