summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authorharanp <haranp@c06c8d41-db1a-0410-9941-cceddc491573>2008-09-18 15:20:46 +0000
committerharanp <haranp@c06c8d41-db1a-0410-9941-cceddc491573>2008-09-18 15:20:46 +0000
commitee45d583173ec10c5027b164437133a0efda79d4 (patch)
tree9fb152d8175ab78e4347ff8ac6acf49ad641ecf8 /crawl-ref/source
parent6cb8f61061f9423b35c3c2e271055db44a8d4b8a (diff)
downloadcrawl-ref-ee45d583173ec10c5027b164437133a0efda79d4.tar.gz
crawl-ref-ee45d583173ec10c5027b164437133a0efda79d4.zip
Clean up monster potion handling, fix bug where !oHW healing
also applied !oH healing, make monsters drink !oH when helpful, disallow potions for some monsters (currently only liches and mummies, more can be added.) Fixes 2035734, 2048006. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@6944 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/enum.h40
-rw-r--r--crawl-ref/source/externs.h4
-rw-r--r--crawl-ref/source/it_use2.h32
-rw-r--r--crawl-ref/source/itemname.h8
-rw-r--r--crawl-ref/source/mon-util.cc141
-rw-r--r--crawl-ref/source/monplace.cc7
-rw-r--r--crawl-ref/source/monstuff.cc114
7 files changed, 206 insertions, 140 deletions
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index fdb8e576a5..e09bb22bae 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -1325,6 +1325,14 @@ enum item_status_flag_type // per item flags: ie. ident status, cursed status
ISFLAG_DROPPED_BY_ALLY = 0x80000000 // Item was dropped by an ally
};
+enum item_type_id_state_type
+{
+ ID_UNKNOWN_TYPE = 0,
+ ID_MON_TRIED_TYPE,
+ ID_TRIED_TYPE,
+ ID_KNOWN_TYPE
+};
+
enum job_type
{
JOB_FIGHTER, // 0
@@ -2249,6 +2257,38 @@ enum player_size_type
PSIZE_PROFILE // profile only (for stealth checks)
};
+enum potion_type
+{
+ POT_HEALING, // 0
+ POT_HEAL_WOUNDS,
+ POT_SPEED,
+ POT_MIGHT,
+ POT_GAIN_STRENGTH,
+ POT_GAIN_DEXTERITY, // 5
+ POT_GAIN_INTELLIGENCE,
+ POT_LEVITATION,
+ POT_POISON,
+ POT_SLOWING,
+ POT_PARALYSIS, // 10
+ POT_CONFUSION,
+ POT_INVISIBILITY,
+ POT_PORRIDGE,
+ POT_DEGENERATION,
+ POT_DECAY, // 15
+ POT_WATER,
+ POT_EXPERIENCE,
+ POT_MAGIC,
+ POT_RESTORE_ABILITIES,
+ POT_STRONG_POISON, // 20
+ POT_BERSERK_RAGE,
+ POT_CURE_MUTATION,
+ POT_MUTATION,
+ POT_RESISTANCE,
+ POT_BLOOD, // 25
+ POT_BLOOD_COAGULATED,
+ NUM_POTIONS // 27
+};
+
enum pronoun_type
{
PRONOUN_CAP, // 0
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 3f409028a5..b8194bcd07 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -1142,6 +1142,10 @@ public:
void apply_enchantments();
void apply_enchantment(const mon_enchant &me);
+ bool can_drink_potion(potion_type ptype) const;
+ bool should_drink_potion(potion_type ptype) const;
+ item_type_id_state_type drink_potion_effect(potion_type ptype);
+
void timeout_enchantments(int levels);
bool is_travelling() const;
diff --git a/crawl-ref/source/it_use2.h b/crawl-ref/source/it_use2.h
index a72a28c741..8ae3e6002c 100644
--- a/crawl-ref/source/it_use2.h
+++ b/crawl-ref/source/it_use2.h
@@ -12,38 +12,6 @@
#include "externs.h"
-enum potion_type
-{
- POT_HEALING, // 0
- POT_HEAL_WOUNDS,
- POT_SPEED,
- POT_MIGHT,
- POT_GAIN_STRENGTH,
- POT_GAIN_DEXTERITY, // 5
- POT_GAIN_INTELLIGENCE,
- POT_LEVITATION,
- POT_POISON,
- POT_SLOWING,
- POT_PARALYSIS, // 10
- POT_CONFUSION,
- POT_INVISIBILITY,
- POT_PORRIDGE,
- POT_DEGENERATION,
- POT_DECAY, // 15
- POT_WATER,
- POT_EXPERIENCE,
- POT_MAGIC,
- POT_RESTORE_ABILITIES,
- POT_STRONG_POISON, // 20
- POT_BERSERK_RAGE,
- POT_CURE_MUTATION,
- POT_MUTATION,
- POT_RESISTANCE,
- POT_BLOOD, // 25
- POT_BLOOD_COAGULATED,
- NUM_POTIONS // 27
-};
-
/* ***********************************************************************
* called from: ability - beam - decks - item_use - misc - religion -
diff --git a/crawl-ref/source/itemname.h b/crawl-ref/source/itemname.h
index c286db6236..54060663a0 100644
--- a/crawl-ref/source/itemname.h
+++ b/crawl-ref/source/itemname.h
@@ -28,14 +28,6 @@ enum item_type_id_type
NUM_IDTYPE
};
-enum item_type_id_state_type // used for values in id[4][50]
-{
- ID_UNKNOWN_TYPE = 0,
- ID_MON_TRIED_TYPE,
- ID_TRIED_TYPE,
- ID_KNOWN_TYPE
-};
-
// [dshaligram] If you edit potion colours/descriptions, also update
// itemname.cc.
enum potion_description_colour_type
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 8d8554f162..8b1afccdbb 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -6693,6 +6693,147 @@ static inline monster_type _royal_jelly_ejectable_monster()
-1 ) );
}
+bool monsters::can_drink_potion(potion_type ptype) const
+{
+ bool rc = true;
+
+ switch (mons_species())
+ {
+ case MONS_LICH:
+ case MONS_MUMMY:
+ rc = false;
+ break;
+ default:
+ break;
+ }
+
+ switch (ptype)
+ {
+ case POT_HEALING:
+ case POT_HEAL_WOUNDS:
+ if (holiness() == MH_UNDEAD
+ || holiness() == MH_NONLIVING
+ || holiness() == MH_PLANT)
+ {
+ rc = false;
+ }
+ break;
+ case POT_BLOOD:
+ case POT_BLOOD_COAGULATED:
+ rc = (mons_species() == MONS_VAMPIRE);
+ break;
+ default:
+ break;
+ }
+
+ return rc;
+}
+
+bool monsters::should_drink_potion(potion_type ptype) const
+{
+ bool rc = false;
+ switch (ptype)
+ {
+ case POT_HEALING:
+ rc = (hit_points <= max_hit_points / 2)
+ || has_ench(ENCH_POISON)
+ || has_ench(ENCH_SICK)
+ || has_ench(ENCH_CONFUSION)
+ || has_ench(ENCH_ROT);
+ break;
+ case POT_HEAL_WOUNDS:
+ rc = (hit_points <= max_hit_points / 2);
+ break;
+ case POT_BLOOD:
+ case POT_BLOOD_COAGULATED:
+ rc = (hit_points <= max_hit_points / 2);
+ break;
+ case POT_SPEED:
+ rc = !has_ench(ENCH_HASTE);
+ break;
+ case POT_INVISIBILITY:
+ // We're being nice: friendlies won't go invisible
+ // if the player won't be able to see them.
+ rc = !has_ench(ENCH_INVIS)
+ && (player_see_invis(false) || !mons_friendly(this));
+ break;
+ default:
+ break;
+ }
+ return rc;
+}
+
+// Return the ID status gained.
+item_type_id_state_type monsters::drink_potion_effect(potion_type ptype)
+{
+ simple_monster_message(this, " drinks a potion.");
+
+ item_type_id_state_type ident = ID_MON_TRIED_TYPE;
+
+ switch (ptype)
+ {
+ case POT_HEALING:
+ {
+ heal(5 + random2(7));
+ simple_monster_message(this, " is healed!");
+
+ const enchant_type cured_enchants[] = {
+ ENCH_POISON, ENCH_SICK, ENCH_CONFUSION, ENCH_ROT
+ };
+
+ // We can differentiate healing and heal wounds (and blood,
+ // for vampires) by seeing if any status ailments are cured.
+ for (unsigned int i = 0; i < ARRAYSZ(cured_enchants); ++i)
+ if (del_ench(cured_enchants[i]))
+ ident = ID_KNOWN_TYPE;
+ }
+ break;
+
+ case POT_HEAL_WOUNDS:
+ heal(10 + random2avg(28, 3));
+ simple_monster_message(this, " is healed!");
+ break;
+
+ case POT_BLOOD:
+ case POT_BLOOD_COAGULATED:
+ if (mons_species() == MONS_VAMPIRE)
+ {
+ heal(10 + random2avg(28, 3));
+ simple_monster_message(this, " is healed!");
+ }
+ break;
+
+ case POT_SPEED:
+ {
+ // XXX FIXME Extract haste() function from mons_ench_f2().
+ bolt beem;
+ beem.target = pos();
+ beem.flavour = BEAM_HASTE;
+ mons_ench_f2(this, beem);
+ if (beem.obvious_effect)
+ ident = ID_KNOWN_TYPE;
+ break;
+ }
+
+ case POT_INVISIBILITY:
+ {
+ // XXX FIXME Extract go_invis() function from mons_ench_f2().
+ bolt beem;
+ beem.target = pos();
+ beem.flavour = BEAM_INVISIBILITY;
+ mons_ench_f2(this, beem);
+ if (beem.obvious_effect)
+ ident = ID_KNOWN_TYPE;
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return ident;
+}
+
void monsters::react_to_damage(int damage, beam_type flavour)
{
// The royal jelly objects to taking damage and will SULK. :-)
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index dab8358c73..a0d80ead9d 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -905,11 +905,8 @@ static int _place_monster_aux( const mgen_data &mg,
menv[id].flags |= MF_BATTY;
}
- if (monster_can_submerge(&menv[id], grd(fpos))
- && !one_chance_in(5))
- {
+ if (monster_can_submerge(&menv[id], grd(fpos)) && !one_chance_in(5))
menv[id].add_ench(ENCH_SUBMERGED);
- }
menv[id].flags |= MF_JUST_SUMMONED;
@@ -2109,7 +2106,7 @@ bool player_angers_monster(monsters *mon)
if (see_grid(mon->pos()) && player_monster_visible(mon))
{
- std::string aura = "";
+ std::string aura;
if (holy)
aura = "holy";
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 30d9c10001..4f233d86fc 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -4301,7 +4301,6 @@ static bool _handle_special_ability(monsters *monster, bolt & beem)
//---------------------------------------------------------------
static bool _handle_potion(monsters *monster, bolt & beem)
{
- // Yes, there is a logic to this ordering {dlb}:
if (mons_is_sleeping(monster)
|| monster->inv[MSLOT_POTION] == NON_ITEM
|| !one_chance_in(3))
@@ -4309,108 +4308,33 @@ static bool _handle_potion(monsters *monster, bolt & beem)
return (false);
}
- bool imbibed = false;
- item_type_id_state_type ident = ID_UNKNOWN_TYPE;
- bool was_visible = (mons_near(monster) && player_monster_visible(monster));
+ bool rc = false;
- const int potion_type = mitm[monster->inv[MSLOT_POTION]].sub_type;
- switch (potion_type)
- {
- case POT_HEALING:
- case POT_HEAL_WOUNDS:
- if (monster->hit_points <= monster->max_hit_points / 2
- && mons_holiness(monster) != MH_UNDEAD
- && mons_holiness(monster) != MH_NONLIVING
- && mons_holiness(monster) != MH_PLANT)
- {
- simple_monster_message(monster, " drinks a potion.");
+ const int potion_idx = monster->inv[MSLOT_POTION];
+ item_def& potion = mitm[potion_idx];
+ const potion_type ptype = static_cast<potion_type>(potion.sub_type);
- if (heal_monster(monster, 5 + random2(7), false))
- {
- simple_monster_message(monster, " is healed!");
- ident = ID_MON_TRIED_TYPE;
- }
-
- if (mitm[monster->inv[MSLOT_POTION]].sub_type == POT_HEAL_WOUNDS)
- {
- heal_monster(monster, 10 + random2avg(28, 3), false);
- }
-
- if (potion_type == POT_HEALING)
- {
- monster->del_ench(ENCH_POISON);
- monster->del_ench(ENCH_SICK);
- if (monster->del_ench(ENCH_CONFUSION))
- ident = ID_KNOWN_TYPE;
- if (monster->del_ench(ENCH_ROT))
- ident = ID_KNOWN_TYPE;
- }
-
- imbibed = true;
- }
- break;
-
- case POT_BLOOD:
- case POT_BLOOD_COAGULATED:
- if (mons_species(monster->type) == MONS_VAMPIRE
- && monster->hit_points <= monster->max_hit_points / 2)
- {
- simple_monster_message(monster, " drinks a potion.");
-
- if (heal_monster(monster, 10 + random2avg(28, 3), false))
- {
- simple_monster_message(monster, " is healed!");
- ident = ID_MON_TRIED_TYPE;
- }
-
- imbibed = true;
- }
- break;
-
- case POT_SPEED:
- // Notice that these are the same odd colours used in
- // mons_ench_f2() {dlb}
- if (monster->has_ench(ENCH_HASTE))
- break;
-
- beem.flavour = BEAM_HASTE;
- // intentional fall through
- case POT_INVISIBILITY:
- if (mitm[monster->inv[MSLOT_POTION]].sub_type == POT_INVISIBILITY)
- {
- if (monster->has_ench(ENCH_INVIS))
- break;
-
- beem.flavour = BEAM_INVISIBILITY;
- // Friendly monsters won't go invisible if the player can't
- // see invisible. We're being nice.
- if (mons_friendly(monster) && !player_see_invis(false))
- break;
- }
+ if (monster->can_drink_potion(ptype) && monster->should_drink_potion(ptype))
+ {
+ const bool was_visible = you.can_see(monster);
- // Allow monsters to drink these when player in sight. (jpeg)
- simple_monster_message(monster, " drinks a potion.");
- mons_ench_f2(monster, beem);
- imbibed = true;
- if (beem.obvious_effect)
- ident = ID_KNOWN_TYPE;
- break;
- }
+ // Drink the potion.
+ const item_type_id_state_type id = monster->drink_potion_effect(ptype);
- if (imbibed)
- {
- if (dec_mitm_item_quantity( monster->inv[MSLOT_POTION], 1 ))
+ // Give ID if necessary.
+ if (was_visible && id != ID_UNKNOWN_TYPE)
+ set_ident_type(OBJ_POTIONS, ptype, id);
+
+ // Remove it from inventory.
+ if (dec_mitm_item_quantity(potion_idx, 1))
monster->inv[MSLOT_POTION] = NON_ITEM;
- else if (is_blood_potion(mitm[monster->inv[MSLOT_POTION]]))
- remove_oldest_blood_potion(mitm[monster->inv[MSLOT_POTION]]);
-
- if (ident != ID_UNKNOWN_TYPE && was_visible)
- set_ident_type(OBJ_POTIONS, potion_type, ident);
+ else if (is_blood_potion(potion))
+ remove_oldest_blood_potion(potion);
monster->lose_energy(EUT_ITEM);
+ rc = true;
}
-
- return (imbibed);
+ return rc;
}
static bool _handle_reaching(monsters *monster)