From beb2b85fcf0ceec4d61a0b0878fc074c86d185ab Mon Sep 17 00:00:00 2001 From: dshaligram Date: Mon, 4 Dec 2006 13:09:35 +0000 Subject: Fix for badness when dropping multiple worn items (Erik). This takes the prize for the most evil case of stack-smashing I've seen in a long while. valgrind rules. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/branches/stone_soup-0.1.5@555 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/delay.cc | 12 ++++++++++-- crawl-ref/source/items.cc | 34 +++++++++++++++++++++++++++++++--- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index 805a2ffff4..0d354cf287 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -54,7 +54,9 @@ static bool is_parent_delay(int delay) // Lua macros can in theory perform any of the other delays, // including travel; in practise travel still assumes there can be // no parent delay. - return (delay == DELAY_TRAVEL || delay == DELAY_MACRO); + return (delay == DELAY_TRAVEL + || delay == DELAY_MACRO + || delay == DELAY_MULTIDROP); } static void push_delay(const delay_queue_item &delay) @@ -318,6 +320,13 @@ void handle_delay( void ) mpr( info, MSGCH_DIAGNOSTICS ); #endif + // delay.duration-- *must* be done before multidrop, because + // multidrop is now a parent delay, which means other delays + // can be pushed to the front of the queue, invalidating the + // "delay" reference here, and resulting in tons of debugging + // fun with valgrind. + delay.duration--; + switch ( delay.type ) { case DELAY_ARMOUR_ON: @@ -351,7 +360,6 @@ void handle_delay( void ) default: break; } - delay.duration--; } else { diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc index d0d9310494..0a2dd2d9f2 100644 --- a/crawl-ref/source/items.cc +++ b/crawl-ref/source/items.cc @@ -94,7 +94,7 @@ void link_items(void) { int i,j; - // first, initailize igrd array + // first, initialise igrd array for (i = 0; i < GXM; i++) { for (j = 0; j < GYM; j++) @@ -1766,8 +1766,7 @@ bool drop_item( int item_dropped, int quant_drop ) { char str_pass[ ITEMNAME_SIZE ]; quant_name( you.inv[item_dropped], quant_drop, DESC_NOCAP_A, str_pass ); - snprintf( info, INFO_SIZE, "You drop %s.", str_pass ); - mpr(info); + mprf( "You drop %s.", str_pass ); if ( grid_destroys_items(my_grid) ) { mprf(MSGCH_SOUND, grid_item_destruction_message(my_grid)); @@ -1859,6 +1858,28 @@ static std::string drop_selitem_text( const std::vector *s ) } std::vector items_for_multidrop; + +// Arrange items that have been selected for multidrop so that +// equipped items are dropped after other items, and equipped items +// are dropped in the same order as their EQ_ slots are numbered. +static bool drop_item_order(const SelItem &first, const SelItem &second) +{ + const item_def &i1 = you.inv[first.slot]; + const item_def &i2 = you.inv[second.slot]; + + const int slot1 = get_equip_slot(&i1), + slot2 = get_equip_slot(&i2); + + if (slot1 != -1 && slot2 != -1) + return (slot1 < slot2); + else if (slot1 != -1 && slot2 == -1) + return (false); + else if (slot2 != -1 && slot1 == -1) + return (true); + + return (first.slot < second.slot); +} + //--------------------------------------------------------------- // // drop @@ -1889,6 +1910,13 @@ void drop(void) return; } + // Sort the dropped items so we don't see weird behaviour when + // dropping a worn robe before a cloak (old behaviour: remove + // cloak, remove robe, wear cloak, drop robe, remove cloak, drop + // cloak). + std::sort( items_for_multidrop.begin(), items_for_multidrop.end(), + drop_item_order ); + if ( items_for_multidrop.size() == 1 ) // only one item { drop_item( items_for_multidrop[0].slot, -- cgit v1.2.3-54-g00ecf