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
Q6WLX2VTRJ3LGDPWBH5WKQM7CIIJ5H6AEIKMXPF2PJA5JX5ZLUZQC
ZO2PZE57FZOUNGR2MEA3ZRRC7DEC7R3NMXLHZMGWROSIYKH2FAWAC
JLAGD2FAV3CWVO7PLXTHLT7MBI23TUSYLSNHFAWP5IB5UO77VKJAC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
542UIZKI65UDRNEMGFFDBWYD5XC7AYLTZ3JZQRR2GHYJALD3YY6QC
L254F6ZIU2HWGLFFGPIORTN4C3TDQ3E5JZ7Z7GQA5AEDIKL6PKDAC
3RNRFLMD2X4RUFTDVITLXAP377YB6F6YMQLL3DAXSUZDZBTWSLRQC
3GSAVTNKEG45AT2U734R5STSRP22WJZL3H6KUFRUWCIA6A4CZE5QC
KBNY5FWKTEAKABFCLPC3QFKFSVZKAGXINPCIFV6WDSWFO4VCKNTAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
BW2JVFBXXFVN5PWDH2KZY5NP4AVH7W755SH5SMRQSAR7F2WFZWNAC
OSGS3PH2L5CBTDVZCZS6OCFQNA4A7RMEXBYJQB7DDZBYYJW7QSSAC
TVC7W7C2XKBQSD2IJFMWFVGXZAOD4EUOW43NAQTOF5KFMAUOJABQC
GPEJOT73KMACP33IPAKFR5ROGHCOIP22VXZMQNYTGLEA2OSZUM2AC
JD3FMKAAAUQZSNPGFLVX7F5H5SWGUSYOFZU4X5W4XYNV6HUKDBKAC
RBAGQ2PB7V5YAM5KSHSZR2E3MLKDSRVM5XYGI2TIXP5QMVBOQHDQC
X5WLJCJVW55SXZVP7IKP7ADCJIGNKN4PKAXFECVR6TNK7XSMZR7QC
4ORX7M2SWZX3WEZWQ7JSFKKT64PTVWEJD4BP5A5UW67HB3PIXRGQC
BSAKBTGIAD3JFZPNLMEI6SOJ2XPT4EJNETZYBW2555ASJTZ2GEGQC
22MF6OUN62WDBJR5QFNJTKU7Q5TIQ76XWCEIRBFWAZDMZUSKJGCAC
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
M2HMYLYYXSP5XGX6MCI77IT6UW5K4YSEUJWHPQPYXVSW5L36BJ2AC
5XSXMOBGXFLTIQE6WDXWWFVDOTUPZSIQ2FWT3YI5QMVU6D76IUYQC
Y2NYY7HWFZ2LQDK3ACSLGS37F2J2IJ5LRGCIMZYXLEOSVPD3A4DAC
bool imbibed = false;
item_type_id_state_type ident = ID_UNKNOWN_TYPE;
bool was_visible = (mons_near(monster) && player_monster_visible(monster));
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.");
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;
bool rc = false;
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;
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);
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);
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);
}
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;
}
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 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