summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/misc.cc
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2009-01-16 07:05:32 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2009-01-16 07:05:32 +0000
commit3c4a60908487170145e20d7a7e298496bef1666f (patch)
tree3282b642e80dfa2b1bc208e54692ac4bc084b00f /crawl-ref/source/misc.cc
parentc4968d0089d5c0d165b38b8f3c3e3f7983d0e191 (diff)
downloadcrawl-ref-3c4a60908487170145e20d7a7e298496bef1666f.tar.gz
crawl-ref-3c4a60908487170145e20d7a7e298496bef1666f.zip
Fix bug #2510110: blood potions coagulating while in a monster's inventory
was causing crashes. Get rid of drop_blood_potions_stack() and pick_up_blood_potions_stack(), replace with the more general merge_blood_potion_stacks() and merge_item_stacks(). When creating blood potions via debug command you can now specify how many turns away from coagulating/rotting it should be. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@8471 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/misc.cc')
-rw-r--r--crawl-ref/source/misc.cc167
1 files changed, 55 insertions, 112 deletions
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index 0befb1a692..4278b7d6fb 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -315,38 +315,44 @@ void maybe_coagulate_blood_potions_floor(int obj)
// Coagulated blood cannot coagulate any further...
ASSERT(blood.sub_type == POT_BLOOD);
- // Now that coagulating is necessary, check square for !coagulated blood.
- ASSERT(blood.pos.x >= 0 && blood.pos.y >= 0);
- for (int o = igrd[blood.pos.x][blood.pos.y]; o != NON_ITEM; o = mitm[o].link)
+ if (!held_by_monster(blood))
{
- if (mitm[o].base_type == OBJ_POTIONS
- && mitm[o].sub_type == POT_BLOOD_COAGULATED)
+ // Now that coagulating is necessary, check square for
+ // !coagulated blood.
+ ASSERT(blood.pos.x >= 0 && blood.pos.y >= 0);
+ for (int o = igrd[blood.pos.x][blood.pos.y]; o != NON_ITEM;
+ o = mitm[o].link)
{
- // Merge with existing stack.
- CrawlHashTable &props2 = mitm[o].props;
- if (!props2.exists("timer"))
- init_stack_blood_potions(mitm[o], mitm[o].special);
-
- ASSERT(props2.exists("timer"));
- CrawlVector &timer2 = props2["timer"].get_vector();
- ASSERT(timer2.size() == mitm[o].quantity);
-
- // Update timer -> push(pop).
- long val;
- while (!age_timer.empty())
+ if (mitm[o].base_type == OBJ_POTIONS
+ && mitm[o].sub_type == POT_BLOOD_COAGULATED)
{
- val = age_timer[age_timer.size() - 1];
- age_timer.pop_back();
- timer2.push_back(val);
+ // Merge with existing stack.
+ CrawlHashTable &props2 = mitm[o].props;
+ if (!props2.exists("timer"))
+ init_stack_blood_potions(mitm[o], mitm[o].special);
+
+ ASSERT(props2.exists("timer"));
+ CrawlVector &timer2 = props2["timer"].get_vector();
+ ASSERT(timer2.size() == mitm[o].quantity);
+
+ // Update timer -> push(pop).
+ long val;
+ while (!age_timer.empty())
+ {
+ val = age_timer[age_timer.size() - 1];
+ age_timer.pop_back();
+ timer2.push_back(val);
+ }
+ _long_sort(timer2);
+ inc_mitm_item_quantity(o, coag_count);
+ ASSERT(timer2.size() == mitm[o].quantity);
+ dec_mitm_item_quantity(obj, rot_count + coag_count);
+ return;
}
- _long_sort(timer2);
- inc_mitm_item_quantity(o, coag_count);
- ASSERT(timer2.size() == mitm[o].quantity);
- dec_mitm_item_quantity(obj, rot_count + coag_count);
- return;
}
}
- // If we got here, nothing was found!
+ // If we got here, nothing was found! (Or it's in a monster's
+ // inventory).
// Entire stack is gone, rotted or coagulated.
// -> Change potions to coagulated type.
@@ -398,10 +404,13 @@ void maybe_coagulate_blood_potions_floor(int obj)
age_timer.pop_back();
timer_new.push_back(val);
}
-
ASSERT(timer_new.size() == coag_count);
props_new.assert_validity();
- move_item_to_grid(&o, blood.pos);
+
+ if (held_by_monster(blood))
+ move_item_to_grid(&o, holding_monster(blood)->pos());
+ else
+ move_item_to_grid(&o, blood.pos);
dec_mitm_item_quantity(obj, rot_count + coag_count);
ASSERT(timer.size() == blood.quantity);
@@ -807,102 +816,36 @@ void remove_newest_blood_potion(item_def &stack, int quant)
_long_sort(timer);
}
-// Called from copy_item_to_grid.
-// NOTE: Quantities are set afterwards, so don't ASSERT for those.
-void drop_blood_potions_stack(item_def &stack, int quant, const coord_def& p)
+void merge_blood_potion_stacks(item_def &source, item_def &dest, int quant)
{
- if (!is_valid_item(stack))
+ if (!is_valid_item(source) || !is_valid_item(dest))
return;
- ASSERT(quant > 0 && quant <= stack.quantity);
- ASSERT(is_blood_potion(stack));
+ ASSERT(quant > 0 && quant <= source.quantity);
+ ASSERT(is_blood_potion(source) && is_blood_potion(dest));
- CrawlHashTable &props = stack.props;
+ CrawlHashTable &props = source.props;
if (!props.exists("timer"))
- init_stack_blood_potions(stack, stack.special);
+ init_stack_blood_potions(source, source.special);
ASSERT(props.exists("timer"));
CrawlVector &timer = props["timer"].get_vector();
ASSERT(!timer.empty());
- // First check whether we can merge with an existing stack on the floor.
- int o = igrd[p.x][p.y];
- while (o != NON_ITEM)
- {
- if (mitm[o].base_type == OBJ_POTIONS
- && mitm[o].sub_type == stack.sub_type)
- {
- CrawlHashTable &props2 = mitm[o].props;
- if (!props2.exists("timer"))
- init_stack_blood_potions(mitm[o], mitm[o].special);
- ASSERT(props2.exists("timer"));
- CrawlVector &timer2 = props2["timer"].get_vector();
-
- // Update timer -> push(pop).
- for (int i = 0; i < quant; i++)
- {
- timer2.push_back(timer[timer.size() - 1].get_long());
- timer.pop_back();
- }
-
- // Re-sort timer.
- _long_sort(timer2);
- return;
- }
- o = mitm[o].link;
- }
-
- // If we got here nothing was found.
- // Stuff could have been destroyed or offered, either case we'll
- // have to reduce the timer vector anyway.
- while (!timer.empty() && quant-- > 0)
- timer.pop_back();
-}
-
-// Called from move_item_to_player.
-// Quantities are set afterwards, so don't ASSERT for those.
-void pick_up_blood_potions_stack(item_def &stack, int quant)
-{
- ASSERT(quant > 0 && quant <= stack.quantity);
- if (!is_valid_item(stack))
- return;
-
- ASSERT(is_blood_potion(stack));
-
- CrawlHashTable &props = stack.props;
- if (!props.exists("timer"))
- init_stack_blood_potions(stack, stack.special);
- ASSERT(props.exists("timer"));
- CrawlVector &timer = props["timer"].get_vector();
- ASSERT(!timer.empty());
+ CrawlHashTable &props2 = dest.props;
+ if (!props2.exists("timer"))
+ init_stack_blood_potions(dest, dest.special);
+ ASSERT(props2.exists("timer"));
+ CrawlVector &timer2 = props2["timer"].get_vector();
- // First check whether we can merge with an existing stack in inventory.
- for (int m = 0; m < ENDOFPACK; m++)
+ // Update timer -> push(pop).
+ for (int i = 0; i < quant; i++)
{
- if (!is_valid_item(you.inv[m]))
- continue;
-
- if (you.inv[m].base_type == OBJ_POTIONS
- && you.inv[m].sub_type == stack.sub_type)
- {
- CrawlHashTable &props2 = you.inv[m].props;
- if (!props2.exists("timer"))
- init_stack_blood_potions(you.inv[m], you.inv[m].special);
- ASSERT(props2.exists("timer"));
- CrawlVector &timer2 = props2["timer"].get_vector();
-
- // Update timer -> push(pop).
- for (int i = 0; i < quant; i++)
- {
- timer2.push_back(timer[timer.size() - 1].get_long());
- timer.pop_back();
- }
-
- // Re-sort timer.
- _long_sort(timer2);
- return;
- }
+ timer2.push_back(timer[timer.size() - 1].get_long());
+ timer.pop_back();
}
- // If we got here nothing was found. Huh?
+
+ // Re-sort timer.
+ _long_sort(timer2);
}
// Deliberately don't check for rottenness here, so this check