Applying Matthew's latest patch (1789869): Identify items you see monsters use.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@2068 c06c8d41-db1a-0410-9941-cceddc491573
L254F6ZIU2HWGLFFGPIORTN4C3TDQ3E5JZ7Z7GQA5AEDIKL6PKDAC
BSI5DB3LVY42ZHOS46X2CAPPVOSOTTQWFGLTMAKRFTROI5BQWFDQC
J6APXOT4QOGQFONWB7G546VTVF6QG42HVOROMHF7YBDJPR4K26OAC
PFEJ4LMDNEKLMGRCMWQ7EIRVU4JMYGICI4G7X4WVWOROVXQCBZ7QC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
ANOEQTM6IGCBTESKKQ5PCBSDTZ7VGRCMDIOAFEH4R7DJHKWKDFAAC
UWMN4HLG6YA2YFQEVIVMDISD6APKEPIZXMMPMNUYCBQDSAUYSXPQC
QS3ZRS3E6KL3YJHPKYEWCWJYRBJSXD5OOYF6Y25HZVECGPJRDB5QC
3GSAVTNKEG45AT2U734R5STSRP22WJZL3H6KUFRUWCIA6A4CZE5QC
C67GX7W5HBCDPQJRSHWMLM4DUJ3ELFSHH42SVICFJVCJW25T5Z3AC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
HDLNRHAMFVDM4QCZMY6COBYZ35ODPR5PONT4UE77UAZ7GEE2FLHQC
4GGNXCX2CLKWQZIZT543LXFFKFRD4PY5XPJFLGWKW4ACKYZNLVPQC
KTXVWUS3MNY7WCPUYZDDU3RVLFKKFLSWRCWKSDNYNMPYZQCVJ24AC
VNHFP63ZLLZU3A3PLXP4BITX57DUIYDHFOHQYK3BOBHV3S64G26QC
CIPVRZGLOZHCERK6YPOBV3P2E4IAB4H6D5EHLRQE2O5E4P4VCBUAC
OQ4KB7QCJSK7GSW3DYBARH4DCB75HFKLUSOSOZZZ4IUFKNGFRUDQC
2KTJHQUX2LTU2BCLS5YXVRRKMOYKKIZAPF2LBKORFGSHEN5IO3IAC
U24V52ZGVQ2XGYA4RNKT26VIIEKUYC6AUEWZSDYJFXB5ZWMMXTPAC
QDTVLBRGHDTRUVT7I3O72K6TMOYAUSAJBZUHGOEFU2RKJNUPWZSQC
R22TTMI6WXWULC7ODKFF3QCB7MOTETQQ6IR4BUCUPOCQKQNCTT5AC
L4PKJZERR7WADKWHY3MR6J6OZFREVPL3CB43I6MLJ2BVKWCUTE7AC
TV3ZC6WOZKSQQJQN26JIVKCHK6UK7WMDBYZDUYRWEAZ4JB4YVNAAC
LW4N5EHKL776DURXZMAM6JEW3JPWWX5BSNP7TCZHTLCDOQTTGFCAC
BNTPYSO6ECZ76CHHLDP3ASSPDSEUH4Y3E3LETKNXVWAWJRFL3YEQC
TJRYL3NXPW5IUGEV3YOC7JYWEXCZDBFPLT4AUG4P227WVKVB72ZAC
HSRRNAU5UAYC6B6IQWGJPFROMZBTJICPCH6DJVZDHDTAGOQ6IOYAC
WLX2RQMMOMP2PYPAGJRM4VFD2WTLJTOAZZPPY3MV76FU2EGEJ54QC
}
}
static void learn_visible_mon_eq_egos(monsters *mon)
{
for (int i = 0; i < NUM_MONSTER_SLOTS; i++)
{
mon_inv_type slot = static_cast<mon_inv_type>(i);
int index = mon->inv[slot];
if (index == NON_ITEM)
continue;
// Alternate weapons aren't wielded (and thus have no
// visible differences) unless the monster can wield two
// weapons at once.
if (slot == MSLOT_ALT_WEAPON && !mons_wields_two_weapons(mon))
continue;
item_def &item = mitm[index];
if (mons_eq_obvious_ego(item, mon))
set_ident_flags(item, ISFLAG_KNOW_TYPE);
int ego = item.special;
switch(ego)
{
case SPWPN_FLAMING:
case SPWPN_FREEZING:
case SPWPN_HOLY_WRATH:
case SPWPN_VENOM:
// Electric branded weapons are constantly crackling
case SPWPN_ELECTROCUTION:
// Unlike SPWPN_FLAME, SPWPN_FROST has a persistant visual effect.
case SPWPN_FROST:
return true;
// SPWPN_FLAME just "glows red for a moment" when first equipped,
// so it isn't obvious after that.
case SPWPN_FLAME:
return false;
}
return false;
}
void monsters::equip(const item_def &item, int slot, int near)
void monsters::equip_armour(item_def &item, int near)
{
if (need_message(near))
mprf("%s wears %s.", name(DESC_CAP_THE).c_str(),
item.name(DESC_NOCAP_A).c_str());
ac += property( item, PARM_AC );
const int armour_plus = item.plus;
ASSERT(abs(armour_plus) < 20);
if (abs(armour_plus) < 20)
ac += armour_plus;
ev += property( item, PARM_EVASION ) / 2;
if (ev < 1)
ev = 1; // This *shouldn't* happen.
}
void monsters::equip(item_def &item, int slot, int near)
{
ac += property( item, PARM_AC );
const int armour_plus = item.plus;
ASSERT(abs(armour_plus) < 20);
if (abs(armour_plus) < 20)
ac += armour_plus;
ev += property( item, PARM_EVASION ) / 2;
if (ev < 1)
ev = 1; // This *shouldn't* happen.
equip_armour(item, near);
void monsters::unequip_weapon(item_def &item, int near)
{
if (need_message(near))
mprf("%s unwields %s.", name(DESC_CAP_THE).c_str(),
item.name(DESC_NOCAP_A).c_str());
const int brand = get_weapon_brand(item);
if (brand == SPWPN_PROTECTION)
ac -= 5;
if (brand != SPWPN_NORMAL && need_message(near))
{
bool message_given = true;
switch (brand)
{
case SPWPN_FLAMING:
mpr("It stops flaming.");
break;
void monsters::unequip(const item_def &item, int slot, int near)
case SPWPN_HOLY_WRATH:
mpr("It stops glowing.");
break;
case SPWPN_ELECTROCUTION:
mpr("It stops crackling.");
break;
case SPWPN_VENOM:
mpr("It stops dripping with poison.");
break;
case SPWPN_DISTORTION:
mpr("Its appearance distorts for a moment.");
break;
default:
message_given = false;
}
if (message_given)
set_ident_flags(item, ISFLAG_KNOW_TYPE);
}
}
void monsters::unequip_armour(item_def &item, int near)
// XXX: Handle armour removal when armour swapping is implemented.
if (need_message(near))
mprf("%s takes off %s.", name(DESC_CAP_THE).c_str(),
item.name(DESC_NOCAP_A).c_str());
ac -= property( item, PARM_AC );
const int armour_plus = item.plus;
ASSERT(abs(armour_plus) < 20);
if (abs(armour_plus) < 20)
ac -= armour_plus;
ev -= property( item, PARM_EVASION ) / 2;
if (ev < 1)
ev = 1; // This *shouldn't* happen.
}
bool monsters::unequip(item_def &item, int slot, int near, bool force)
{
if (item.cursed() && !force)
return false;
if (!force && mons_near(this) && player_monster_visible(this))
set_ident_flags(item, ISFLAG_KNOW_CURSE);
if (get_weapon_brand(item) == SPWPN_PROTECTION)
ac -= 5;
unequip_weapon(item, near);
break;
// Armour swapping not implemented yet, but armour can be
// removed if wizard forces monster to wear a new piece of
// armour with the "give item" wizard command.
case OBJ_ARMOUR:
unequip_armour(item, near);
// Cannot drop cursed weapon or armour.
if ((eslot == MSLOT_WEAPON || eslot == MSLOT_ARMOUR)
&& mitm[index].cursed())
return (false);
// Unequip equipped items before dropping them; unequip() prevents
// cursed items from being removed.
bool was_unequipped = false;
if (eslot == MSLOT_WEAPON || eslot == MSLOT_ARMOUR
|| (eslot == MSLOT_ALT_WEAPON && mons_wields_two_weapons(this) ))
{
if (!unequip(mitm[index], eslot, near))
return (false);
was_unequipped = true;
}
if (defender->atype() == ACT_PLAYER && attacker_visible
&& weapon != NULL && !is_artefact(*weapon))
{
// If the player is being sent to the Abyss by being attacked
// with a distortion weapon, then we have to ID it before
// the player goes to Abyss, while the weapon object is
// still in memory.
set_ident_flags(*weapon, ISFLAG_KNOW_TYPE);
}
else if (defender_visible)
obvious_effect = true;
#ifdef WIZARD
void wizard_give_monster_item(monsters *mon)
{
mon_itemuse_type item_use = mons_itemuse( mon->type );
if (item_use < MONUSE_STARTING_EQUIPMENT)
{
mpr("That type of monster can't use any items.");
return;
}
int player_slot = prompt_invent_item( "Give which item to monster?",
MT_DROP, -1 );
if (player_slot == PROMPT_ABORT)
return;
for (int i = 0; i < NUM_EQUIP; i++)
if (you.equip[i] == player_slot)
{
mpr("Can't give equipped items to a monster.");
return;
}
item_def &item = you.inv[player_slot];
mon_inv_type mon_slot;
switch(item.base_type)
{
case OBJ_WEAPONS:
// Let wizard specify which slot to put weapon into via
// inscriptions.
if (item.inscription.find("first") != std::string::npos
|| item.inscription.find("primary") != std::string::npos)
{
mpr("Putting weapon into primary slot by inscription");
mon_slot = MSLOT_WEAPON;
break;
}
else if (item.inscription.find("second") != std::string::npos
|| item.inscription.find("alt") != std::string::npos)
{
mpr("Putting weapon into alt slot by inscription");
mon_slot = MSLOT_ALT_WEAPON;
break;
}
// For monsters which can wield two weapons, prefer whichever
// slot is empty (if there is an empty slot).
if (mons_wields_two_weapons(mon))
{
if (mon->inv[MSLOT_WEAPON] == NON_ITEM)
{
mpr("Dual wielding monster, putting into empty primary slot");
mon_slot = MSLOT_WEAPON;
break;
}
else if (mon->inv[MSLOT_ALT_WEAPON] == NON_ITEM)
{
mpr("Dual wielding monster, putting into empty alt slot");
mon_slot = MSLOT_ALT_WEAPON;
break;
}
}
// Try to replace a ranged weapon with a ranged weapon and
// a non-ranged weapon with a non-ranged weapon
if (mon->inv[MSLOT_WEAPON] != NON_ITEM
&& (is_range_weapon(mitm[mon->inv[MSLOT_WEAPON]])
== is_range_weapon(item)))
{
mpr("Replacing primary slot with similar weapon");
mon_slot = MSLOT_WEAPON;
break;
}
if (mon->inv[MSLOT_ALT_WEAPON] != NON_ITEM
&& (is_range_weapon(mitm[mon->inv[MSLOT_ALT_WEAPON]])
== is_range_weapon(item)))
{
mpr("Replacing alt slot with similar weapon");
mon_slot = MSLOT_ALT_WEAPON;
break;
}
// Prefer the empty slot (if any)
if (mon->inv[MSLOT_WEAPON] == NON_ITEM)
{
mpr("Putting weapon into empty primary slot");
mon_slot = MSLOT_WEAPON;
break;
}
else if (mon->inv[MSLOT_ALT_WEAPON] == NON_ITEM)
{
mpr("Putting weapon into empty alt slot");
mon_slot = MSLOT_ALT_WEAPON;
break;
}
// Default to primary weapon slot
mpr("Defaulting to primary slot");
mon_slot = MSLOT_WEAPON;
break;
case OBJ_ARMOUR:
mon_slot = MSLOT_ARMOUR;
break;
case OBJ_MISSILES:
mon_slot = MSLOT_MISSILE;
break;
case OBJ_WANDS:
mon_slot = MSLOT_WAND;
break;
case OBJ_SCROLLS:
mon_slot = MSLOT_SCROLL;
break;
case OBJ_POTIONS:
mon_slot = MSLOT_POTION;
break;
case OBJ_MISCELLANY:
mon_slot = MSLOT_MISCELLANY;
break;
default:
mpr("You can't give that type of item to a monster.");
return;
}
// Shouldn't be be using MONUSE_MAGIC_ITEMS?
if (item_use == MONUSE_STARTING_EQUIPMENT
&& !mons_is_unique( mon->type ))
{
switch(mon_slot)
{
case MSLOT_WEAPON:
case MSLOT_ALT_WEAPON:
case MSLOT_ARMOUR:
case MSLOT_MISSILE:
break;
default:
mpr("That type of monster can only use weapons and armour.");
return;
}
}
int index = get_item_slot(10);
if (index == NON_ITEM)
{
mpr("Too many items on level, bailing.");
return;
}
// Move monster's old item to player's inventory as last step
int old_eq = NON_ITEM;
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);
}
item_def &new_item = mitm[index];
new_item = item;
new_item.link = NON_ITEM;
new_item.x = 0;
new_item.y = 0;
mon->inv[mon_slot] = index;
// 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);
// Item is gone from player's inventory
dec_inv_item_quantity(player_slot, item.quantity);
// Monster's old item moves to player's inventory.
if (old_eq != NON_ITEM)
{
mpr("Fetching monster's old item.");
move_item_to_player(old_eq, mitm[old_eq].quantity);
}
}
#endif
// Forget things that nearby monsters are carrying, as well
// (for use with the "give monster an item" wizard targetting
// command).
for (i = 0; i < MAX_MONSTERS; i++)
{
monsters* mon = &menv[i];
if (!invalid_monster(mon) && mons_near(mon))
{
for (j = 0; j < NUM_MONSTER_SLOTS; j++)
{
if (mon->inv[j] == NON_ITEM)
continue;
item_def &item = mitm[mon->inv[j]];
if (!is_valid_item(item))
continue;
set_ident_type( item.base_type, item.sub_type,
ID_UNKNOWN_TYPE );
unset_ident_flags( item, ISFLAG_IDENT_MASK );
}
}
}