summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2009-01-08 06:34:25 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2009-01-08 06:34:25 +0000
commit2af58b0346183d18125bfa5867be4339ce055ffe (patch)
tree937b1e45d0d7e8faa72b859c09f7e68b8ea8d273
parent3fe0cf688e2dad0503dbb31dd43cfe3bd1fa6536 (diff)
downloadcrawl-ref-2af58b0346183d18125bfa5867be4339ce055ffe.tar.gz
crawl-ref-2af58b0346183d18125bfa5867be4339ce055ffe.zip
Make the position of monster held items (-2, -2) rather than (0, 0), so that
any valid item in mitm[] which is still at (0, 0) by the time debug_item_scan() is called must be buggy. Also set the link fields of monster held items to NON_ITEM + 1 + monster_index, so that it's easy to tell which monster is holding any given item; this is used in debug_mons_scan() and monsters::pickup() to do some sanity checking of monster inventory. I've tried to thoroughly test this, but there might still be some bugs left. Breaks savefile compatibility (or, rather, will lead to endless error messages if you use an old save file). git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@8322 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r--crawl-ref/source/acr.cc2
-rw-r--r--crawl-ref/source/debug.cc131
-rw-r--r--crawl-ref/source/dungeon.cc13
-rw-r--r--crawl-ref/source/externs.h5
-rw-r--r--crawl-ref/source/files.cc22
-rw-r--r--crawl-ref/source/items.cc62
-rw-r--r--crawl-ref/source/makeitem.cc7
-rw-r--r--crawl-ref/source/mon-util.cc62
-rw-r--r--crawl-ref/source/mon-util.h2
-rw-r--r--crawl-ref/source/mtransit.cc4
-rw-r--r--crawl-ref/source/spells2.cc12
-rw-r--r--crawl-ref/source/spells3.cc7
-rw-r--r--crawl-ref/source/tags.cc10
13 files changed, 246 insertions, 93 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index e017f96054..946050484b 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -1165,7 +1165,7 @@ static void _do_wizard_command(int wiz_command, bool silent_fail)
for (int i = 0; i < MAX_ITEMS; i++)
{
item_def &item(mitm[i]);
- if (!is_valid_item(item) || item.pos.x == 0 || item.pos.y == 0)
+ if (!is_valid_item(item) || held_by_monster(item))
continue;
if (item.link != NON_ITEM)
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc
index c697fb51ca..26675953c9 100644
--- a/crawl-ref/source/debug.cc
+++ b/crawl-ref/source/debug.cc
@@ -2117,7 +2117,7 @@ void debug_item_scan( void )
{
for (int y = 0; y < GYM; y++)
{
- // These are unlinked monster inventory items -- skip them:
+ // Unlinked temporary items.
if (x == 0 && y == 0)
continue;
@@ -2162,8 +2162,21 @@ void debug_item_scan( void )
strcpy(name, mitm[i].name(DESC_PLAIN).c_str());
- // Don't check (-1,-1) player items or (0,0) monster items
- if ((mitm[i].pos.x > 0 || mitm[i].pos.y > 0) && !visited[i])
+ const monsters* mon = holding_monster(mitm[i]);
+
+ // Don't check (-1,-1) player items or (-2, -2) monstert items
+ // (except to make sure that the monster is alive).
+ if (mitm[i].pos.origin())
+ {
+ mpr( "Unlinked temporary item:", MSGCH_ERROR );
+ _dump_item( name, i, mitm[i] );
+ }
+ else if (mon != NULL && !mon->type == -1)
+ {
+ mpr( "Unlinked item held by dead monster:", MSGCH_ERROR );
+ _dump_item( name, i, mitm[i] );
+ }
+ else if ((mitm[i].pos.x > 0 || mitm[i].pos.y > 0) && !visited[i])
{
mpr( "Unlinked item:", MSGCH_ERROR );
_dump_item( name, i, mitm[i] );
@@ -2381,7 +2394,8 @@ void debug_mons_scan()
_announce_level_prob(warned);
mprf(MSGCH_WARN, "Floating monster: %s at (%d,%d)",
- m->name(DESC_PLAIN, true).c_str(), m->pos().x, m->pos().y);
+ m->full_name(DESC_PLAIN, true).c_str(),
+ m->pos().x, m->pos().y);
warned = true;
for (int j = 0; j < MAX_MONSTERS; ++j)
{
@@ -2397,17 +2411,79 @@ void debug_mons_scan()
{
mprf(MSGCH_WARN, "Also at (%d, %d): %s",
m->pos().x, m->pos().y,
- m2->name(DESC_PLAIN, true).c_str());
+ m2->full_name(DESC_PLAIN, true).c_str());
}
else if (m2->type != -1)
{
mprf(MSGCH_WARN, "Dead mon also at (%d, %d): %s",
m->pos().x, m->pos().y,
- m2->name(DESC_PLAIN, true).c_str());
+ m2->full_name(DESC_PLAIN, true).c_str());
}
}
- }
- }
+ } // if (mgrd(m->pos()) != i)
+
+ for (int j = 0; j < NUM_MONSTER_SLOTS; j++)
+ {
+ const int idx = m->inv[j];
+ if (idx == NON_ITEM)
+ continue;
+
+ item_def &item(mitm[idx]);
+
+ if (!is_valid_item(item))
+ {
+ _announce_level_prob(warned);
+ warned = true;
+ mprf(MSGCH_WARN, "Monster %s (%d, %d) holding invalid item in "
+ "slot %d.",
+ m->full_name(DESC_PLAIN, true).c_str(),
+ m->pos().x, m->pos().y, j);
+ continue;
+ }
+
+ const monsters* holder = holding_monster(item);
+
+ if (holder == NULL)
+ {
+ _announce_level_prob(warned);
+ warned = true;
+ mprf(MSGCH_WARN, "Monster %s (%d, %d) holding non-monster "
+ "item.",
+ m->full_name(DESC_PLAIN, true).c_str(),
+ m->pos().x, m->pos().y);
+ _dump_item( item.name(DESC_PLAIN, false, true).c_str(),
+ idx, item );
+ continue;
+ }
+
+ if (holder != m)
+ {
+ _announce_level_prob(warned);
+ warned = true;
+ mprf(MSGCH_WARN, "Monster %s (%d, %d) holding item %s, but "
+ "item think's it's held by monster %s "
+ "(%d, %d)",
+ m->full_name(DESC_PLAIN, true).c_str(),
+ m->pos().x, m->pos().y,
+ holder->full_name(DESC_PLAIN, true).c_str(),
+ holder->pos().x, holder->pos().y);
+
+ bool found = false;
+ for (int k = 0; k < NUM_MONSTER_SLOTS; k++)
+ {
+ if (holder->inv[k] == idx)
+ {
+ mpr("Other monster thinks it's holding the item, too.",
+ MSGCH_WARN);
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ mpr("Other monster isn't holding it, though.", MSGCH_WARN);
+ } // if (holder != m)
+ } // for (int j = 0; j < NUM_MONSTER_SLOTS; j++)
+ } // for (int i = 0; i < MAX_MONSTERS; ++i)
// No problems?
if (!warned)
@@ -4797,7 +4873,6 @@ void wizard_give_monster_item(monsters *mon)
}
int index = get_item_slot(10);
-
if (index == NON_ITEM)
{
mpr("Too many items on level, bailing.");
@@ -4805,36 +4880,44 @@ void wizard_give_monster_item(monsters *mon)
}
// Move monster's old item to player's inventory as last step.
- int old_eq = NON_ITEM;
+ int old_eq = NON_ITEM;
+ bool unequipped = false;
if (mon->inv[mon_slot] != NON_ITEM)
{
old_eq = mon->inv[mon_slot];
-
// Alternative weapons don't get (un)wielded unless the monster
// can wield two weapons.
if (mon_slot != MSLOT_ALT_WEAPON || mons_wields_two_weapons(mon))
+ {
mon->unequip(*(mon->mslot_item(mon_slot)), mon_slot, 1, true);
+ unequipped = true;
+ }
+ mon->inv[mon_slot] = NON_ITEM;
}
- item_def &new_item = mitm[index];
- new_item = item;
- new_item.link = NON_ITEM;
- new_item.pos.reset();
-
- mon->inv[mon_slot] = index;
+ mitm[index] = item;
- // Alternative weapons don't get (un)wielded unless the monster
- // can wield two weapons.
- if (mon_slot != MSLOT_ALT_WEAPON || mons_wields_two_weapons(mon))
- mon->equip(new_item, mon_slot, 1);
+ unwind_var<int> save_speedinc(mon->speed_increment);
+ if (!mon->pickup_item(mitm[index], false, true))
+ {
+ mpr("Monster wouldn't take item.");
+ if (old_eq != NON_ITEM)
+ {
+ mon->inv[mon_slot] = old_eq;
+ if (unequipped)
+ mon->equip(mitm[old_eq], mon_slot, 1);
+ }
+ mitm[index].clear();
+ return;
+ }
// Item is gone from player's inventory
dec_inv_item_quantity(player_slot, item.quantity);
- if ((mon->flags & MF_HARD_RESET) && !(new_item.flags & ISFLAG_SUMMONED))
+ if ((mon->flags & MF_HARD_RESET) && !(item.flags & ISFLAG_SUMMONED))
mprf(MSGCH_WARN, "WARNING: Monster has MF_HARD_RESET and all its "
"items will disappear when it does.");
- else if ((new_item.flags & ISFLAG_SUMMONED) && !mon->is_summoned())
+ else if ((item.flags & ISFLAG_SUMMONED) && !mon->is_summoned())
mprf(MSGCH_WARN, "WARNING: Item is summoned and will disappear when "
"the monster does.");
@@ -4846,6 +4929,8 @@ void wizard_give_monster_item(monsters *mon)
mprf(MSGCH_WARN, "WARNING: Item is summoned and shouldn't really "
"be anywhere but in the inventory of a summoned monster.");
+ mitm[old_eq].pos.reset();
+ mitm[old_eq].link = NON_ITEM;
move_item_to_player(old_eq, mitm[old_eq].quantity);
}
}
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index 5a587c2a45..20df74f463 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -1087,8 +1087,11 @@ static void _fixup_misplaced_items()
for (int i = 0; i < MAX_ITEMS; i++)
{
item_def& item(mitm[i]);
- if (!is_valid_item(item) || (item.pos.x == 0))
+ if (!is_valid_item(item) || (item.pos.x == 0)
+ || held_by_monster(item))
+ {
continue;
+ }
if (in_bounds(item.pos))
{
@@ -5598,7 +5601,10 @@ void place_spec_shop( int level_number,
if (orb != NON_ITEM && _need_varied_selection(env.shop[i].type))
{
if (!one_chance_in(stocked[mitm[orb].sub_type] + 1))
+ {
+ mitm[orb].clear();
orb = NON_ITEM; // try again
+ }
}
if (orb != NON_ITEM
@@ -5612,10 +5618,7 @@ void place_spec_shop( int level_number,
// Reset object and try again.
if (orb != NON_ITEM)
- {
- mitm[orb].base_type = OBJ_UNASSIGNED;
- mitm[orb].quantity = 0;
- }
+ mitm[orb].clear();
}
if (orb == NON_ITEM)
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 7dc87f11a9..86d93be0d4 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -220,6 +220,11 @@ struct coord_def
{
return origin();
}
+
+ bool equals(const int xi, const int yi) const
+ {
+ return (xi == x && yi == y);
+ }
};
class actor
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index f9e4b4cf73..8376a17824 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -804,26 +804,6 @@ bool travel_load_map( branch_type branch, int absdepth )
return (true);
}
-static void _sanity_test_monster_inventory()
-{
- // Sanity forcing of monster inventory items (required?)
- for (int i = 0; i < MAX_MONSTERS; i++)
- {
- if (menv[i].type == -1)
- continue;
-
- for (int j = 0; j < NUM_MONSTER_SLOTS; j++)
- {
- if (menv[i].inv[j] == NON_ITEM)
- continue;
-
- // items carried by monsters shouldn't be linked
- if (mitm[menv[i].inv[j]].link != NON_ITEM)
- mitm[menv[i].inv[j]].link = NON_ITEM;
- }
- }
-}
-
static void _place_player_on_stair(level_area_type old_level_type,
branch_type old_branch,
int stair_taken)
@@ -1256,8 +1236,6 @@ bool load( dungeon_feature_type stair_taken, load_mode_type load_mode,
_redraw_all();
- _sanity_test_monster_inventory();
-
if (load_mode != LOAD_VISITOR)
dungeon_events.fire_event(DET_ENTERING_LEVEL);
diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc
index 200656794c..7dff728830 100644
--- a/crawl-ref/source/items.cc
+++ b/crawl-ref/source/items.cc
@@ -110,13 +110,18 @@ void link_items(void)
igrd.init(NON_ITEM);
// Link all items on the grid, plus shop inventory,
- // but DON'T link the huge pile of monster items at (0,0).
+ // but DON'T link the huge pile of monster items at (-2,-2).
for (int i = 0; i < MAX_ITEMS; i++)
{
- if (!is_valid_item(mitm[i]) || mitm[i].pos.origin())
+ // Don't mess with monster held items, since the index of the holding
+ // monster is stored in the link field.
+ if (held_by_monster(mitm[i]))
+ continue;
+
+ if (!is_valid_item(mitm[i]))
{
- // Item is not assigned, or is monster item. Ignore.
+ // Item is not assigned. Ignore.
mitm[i].link = NON_ITEM;
continue;
}
@@ -365,37 +370,39 @@ void unlink_item( int dest )
if (dest == NON_ITEM || !is_valid_item( mitm[dest] ))
return;
- if (mitm[dest].pos.origin())
+ monsters* monster = holding_monster(mitm[dest]);
+
+ if (monster != NULL)
{
- // (0,0) is where the monster items are (and they're unlinked by igrd),
- // although it also contains items that are not linked in yet.
- //
- // Check if a monster has it:
- for (int c = 0; c < MAX_MONSTERS; c++)
+ for (int i = 0; i < NUM_MONSTER_SLOTS; i++)
{
- monsters *monster = &menv[c];
-
- if (monster->type == -1)
- continue;
-
- for (int cy = 0; cy < NUM_MONSTER_SLOTS; cy++)
+ if (monster->inv[i] == dest)
{
- if (monster->inv[cy] == dest)
- {
- monster->inv[cy] = NON_ITEM;
+ monster->inv[i] = NON_ITEM;
- mitm[dest].pos.reset();
- mitm[dest].link = NON_ITEM;
- return;
- }
+ mitm[dest].pos.reset();
+ mitm[dest].link = NON_ITEM;
+ return;
}
}
-
- // Always return because this item might just be temporary.
+ mprf(MSGCH_ERROR, "Item %s claims to be held by monster %s, but "
+ "it isn't in the monster's inventory.",
+ mitm[dest].name(DESC_PLAIN, false, true).c_str(),
+ monster->name(DESC_PLAIN, true).c_str());
+ // Don't return so the debugging code can take a look at it.
+ }
+ // Unlinking a newly created item, or a a temporary one, or an item in
+ // the player's inventory.
+ else if (mitm[dest].pos.origin() || mitm[dest].pos.equals(-1, -1))
+ {
+ mitm[dest].pos.reset();
+ mitm[dest].link = NON_ITEM;
return;
}
else
{
+ ASSERT(in_bounds(mitm[dest].pos));
+
// Linked item on map:
//
// Use the items (x,y) to access the list (igrd[x][y]) where
@@ -1629,8 +1636,11 @@ int move_item_to_player( int obj, int quant_got, bool quiet,
}
coord_def p = mitm[obj].pos;
- dungeon_events.fire_position_event(
- dgn_event(DET_ITEM_PICKUP, p, 0, obj, -1), p);
+ // If moving an item directly from a monster to the player without the
+ // item having been on the grid, then it really isn't a position event.
+ if (in_bounds(p))
+ dungeon_events.fire_position_event(
+ dgn_event(DET_ITEM_PICKUP, p, 0, obj, -1), p);
item_def &item = you.inv[freeslot];
// Copy item.
diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc
index 85ab12bd5b..714c614e1d 100644
--- a/crawl-ref/source/makeitem.cc
+++ b/crawl-ref/source/makeitem.cc
@@ -2897,11 +2897,12 @@ static void _give_monster_item(monsters *mon, int thing,
bool (monsters::*pickupfn)(item_def&, int) = NULL)
{
item_def &mthing = mitm[thing];
+ ASSERT(is_valid_item(mthing));
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS,
"Giving %s to %s...", mthing.name(DESC_PLAIN).c_str(),
- mon->name(DESC_PLAIN).c_str());
+ mon->name(DESC_PLAIN, true).c_str());
#endif
mthing.pos.reset();
@@ -2922,9 +2923,11 @@ static void _give_monster_item(monsters *mon, int thing,
mprf(MSGCH_DIAGNOSTICS, "Destroying %s because %s doesn't want it!",
mthing.name(DESC_PLAIN).c_str(), mon->name(DESC_PLAIN).c_str());
#endif
- destroy_item(thing);
+ destroy_item(thing, true);
return;
}
+ ASSERT(is_valid_item(mthing));
+ ASSERT(holding_monster(mthing) == mon);
if (!force_item || mthing.colour == BLACK)
item_colour( mthing );
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 1a0699d392..39d115431a 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -4188,8 +4188,65 @@ void monsters::pickup_message(const item_def &item, int near)
}
}
+bool held_by_monster(const item_def &item)
+{
+ return (item.pos.equals(-2, -2)
+ && !invalid_monster_index(item.link - NON_ITEM - 1));
+}
+
+monsters* holding_monster(const item_def &item)
+{
+ if (!item.pos.equals(-2, -2))
+ return (NULL);
+ const int midx = item.link - NON_ITEM - 1;
+ if (invalid_monster_index(midx))
+ return (NULL);
+
+ return (&menv[midx]);
+}
+
bool monsters::pickup(item_def &item, int slot, int near, bool force_merge)
{
+ ASSERT(is_valid_item(item));
+
+ const monsters *other_mon = holding_monster(item);
+
+ if (other_mon != NULL)
+ {
+ if (other_mon == this)
+ {
+ if (inv[slot] == item.index())
+ {
+ mprf(MSGCH_DIAGNOSTICS, "Monster %s already holding item %s.",
+ name(DESC_PLAIN, true).c_str(),
+ item.name(DESC_PLAIN, false, true).c_str());
+ return (false);
+ }
+ else
+ {
+ mprf(MSGCH_DIAGNOSTICS, "Items %s thinks it's alread held by "
+ "monster %s.",
+ item.name(DESC_PLAIN, false, true).c_str(),
+ name(DESC_PLAIN, true).c_str());
+ }
+ }
+ else if (other_mon->type == -1)
+ {
+ mprf(MSGCH_DIAGNOSTICS, "Item %s, held by dead monster, being "
+ "picked up by monster %s.",
+ item.name(DESC_PLAIN, false, true).c_str(),
+ name(DESC_PLAIN, true).c_str());
+ }
+ else
+ {
+ mprf(MSGCH_DIAGNOSTICS, "Item %s, held by monster %s, being "
+ "picked up by monster %s.",
+ item.name(DESC_PLAIN, false, true).c_str(),
+ other_mon->name(DESC_PLAIN, true).c_str(),
+ name(DESC_PLAIN, true).c_str());
+ }
+ }
+
// If a monster chooses a two-handed weapon as main weapon, it will
// first have to drop any shield it might wear.
// (Monsters will always favour damage over protection.)
@@ -4227,8 +4284,12 @@ bool monsters::pickup(item_def &item, int slot, int near, bool force_merge)
const int item_index = item.index();
unlink_item(item_index);
+
inv[slot] = item_index;
+ item.pos.set(-2, -2);
+ item.link = NON_ITEM + 1 + mindex();
+
pickup_message(item, near);
equip(item, slot, near);
lose_pickup_energy();
@@ -4271,6 +4332,7 @@ bool monsters::drop_item(int eslot, int near)
item.quantity > 1 ? "them" : "it");
item_was_destroyed(item, mindex());
+ destroy_item(item_index);
}
else if (!move_item_to_grid(&item_index, pos()))
{
diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h
index 789d424eb0..d76302d155 100644
--- a/crawl-ref/source/mon-util.h
+++ b/crawl-ref/source/mon-util.h
@@ -856,4 +856,6 @@ bool mons_can_pass(const monsters *mon, dungeon_feature_type grid);
mon_inv_type equip_slot_to_mslot(equipment_type eq);
mon_inv_type item_to_mslot(const item_def &item);
+bool held_by_monster(const item_def &item);
+monsters* holding_monster(const item_def &item);
#endif
diff --git a/crawl-ref/source/mtransit.cc b/crawl-ref/source/mtransit.cc
index d49c053cc3..14f37c4d66 100644
--- a/crawl-ref/source/mtransit.cc
+++ b/crawl-ref/source/mtransit.cc
@@ -316,8 +316,8 @@ void follower::restore_mons_items(monsters &m)
item_def &it = mitm[islot];
it = items[i];
- it.pos.reset();
- it.link = NON_ITEM;
+ it.pos.set(-2, -2);
+ it.link = NON_ITEM + 1 + m.mindex();
}
}
}
diff --git a/crawl-ref/source/spells2.cc b/crawl-ref/source/spells2.cc
index b76445aad2..48ff558ec8 100644
--- a/crawl-ref/source/spells2.cc
+++ b/crawl-ref/source/spells2.cc
@@ -1718,6 +1718,11 @@ bool cast_tukimas_dance(int pow, god_type god,
if (i == NON_ITEM)
success = false;
+ else
+ // Copy item now so that mitm[i] is occupied and doesn't get picked
+ // by get_item_slot() when giving the dancing weapon it's item
+ // during create_monster().
+ mitm[i] = you.inv[wpn];
int monster;
@@ -1736,7 +1741,10 @@ bool cast_tukimas_dance(int pow, god_type god,
0, god));
if (monster == -1)
+ {
+ mitm[i].clear();
success = false;
+ }
}
if (!success)
@@ -1760,8 +1768,8 @@ bool cast_tukimas_dance(int pow, god_type god,
// Copy the unwielded item.
mitm[i] = you.inv[wpn];
mitm[i].quantity = 1;
- mitm[i].pos.reset();
- mitm[i].link = NON_ITEM;
+ mitm[i].pos.set(-2, -2);
+ mitm[i].link = NON_ITEM + 1 + monster;
// Mark the weapon as thrown, so that we'll autograb it when the
// tango's done.
diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc
index 46b10f6558..20a478ccd1 100644
--- a/crawl-ref/source/spells3.cc
+++ b/crawl-ref/source/spells3.cc
@@ -813,11 +813,8 @@ void equip_undead(const coord_def &a, int corps, int monster, int monnum)
if (mon->inv[mslot] != NON_ITEM)
return;
- unlink_item(objl);
- mon->inv[mslot] = objl;
-
- if (mslot != MSLOT_ALT_WEAPON || mons_wields_two_weapons(mon))
- mon->equip(item, mslot, 0);
+ unwind_var<int> save_speedinc(mon->speed_increment);
+ mon->pickup_item(mitm[objl], false, true);
} // while
}
diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc
index e5ff017648..fde326b19b 100644
--- a/crawl-ref/source/tags.cc
+++ b/crawl-ref/source/tags.cc
@@ -1767,11 +1767,11 @@ void marshallItem(writer &th, const item_def &item)
marshallShort(th, item.pos.y);
marshallLong(th, item.flags);
- marshallShort(th, item.link); // unused
- if (item.pos.x == -1 && item.pos.y == -1)
- marshallShort(th, -1); // unused
- else
+ marshallShort(th, item.link);
+ if (item.pos.x >= 0 && item.pos.y >= 0)
marshallShort(th, igrd(item.pos)); // unused
+ else
+ marshallShort(th, -1); // unused
marshallByte(th, item.slot);
@@ -1794,8 +1794,8 @@ void unmarshallItem(reader &th, item_def &item)
item.pos.x = unmarshallShort(th);
item.pos.y = unmarshallShort(th);
item.flags = (unsigned long) unmarshallLong(th);
+ item.link = unmarshallShort(th);
- unmarshallShort(th); // mitm[].link -- unused
unmarshallShort(th); // igrd[item.x][item.y] -- unused
item.slot = unmarshallByte(th);