functions which check if you can or can't wear something…that should be cleaned up.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@9115 c06c8d41-db1a-0410-9941-cceddc491573
NDP5ANTLTYSDYLBHZPEJLO6IDU6OKA6UQHYWSBUXEEPYHZLRTYNQC
X2AT73U3LOWYTSLNNVIKOWFTV5YVTR5XW22RST7F6DAMIBQBF3XQC
LTEHVF5JJAZ4M4RXLHCEEFQFTSDC5EUE44HRAQQ666FFPMTQZA6AC
B47JR5HJJPDKC7TIHP4BDT536J6MZNOJK36MQJNPAIH7OFYFCXSAC
2BQFPAKR5PIVX4OW6P3NAWKEL37HZ4TTAZDC4JQNC7P5EMQEBRPQC
X55CKEKNO5RD2JMQ4MYX6PXQLDMLH4U4PPKSBK5EQ622J5HOPD2AC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
3BJ2OOF4F524G6UKVGOZVT6W3FSTSHHTKRJADUBZCHDXZWV3KANQC
H5BVKRORNXTCJKFXQPTFWDURKSUFW24CGSJXBGZCJUP4DHMSVDBQC
2PVXJ5KNSQHRQLAYXEGWVSQEDEN24J3BCH46Z7I7QWNBLCCCIZ3AC
UPPUAHXHWKGQWDKOCVLR7RG3SHEUVKOUC5GRYCEUDGD6RNCOU5LAC
5NEEYVF4MHEA536IUWEOSE2YQYKPK7CVH2Q7TYPS674V5KQZILNQC
6ZBNP5FQRPWMZYXUO6N7RW5ZN7TJCYYLBNMHYYVSPXCYRQFCQ6YAC
EYYWIH7377INOKPRABJUATNQ2YWKLOVHZKQIY55POX2YXVMDDWAAC
KHHAE5ZK7ITEZVMMUKYROKECLE2RU5ZU5OQ4Z4XSRQXE2R65O67AC
IP4A3VRYFYIVLRUAU4DF4KDNP6E4UISWJX3LI2F4EGSSMIJYRJXAC
6CZYPP67SB2M3SQS3QIPJWHZY7PJIRTTBH5CLORV3AALVTJIL5MQC
7F5A7R3P2V3SPUNNJMOEG5ISKKANHC5C5G34YV77QCLQP2T3BV2QC
ZYBZFZJRHBI7IMLOY7S4BXLJAMOXPK6GWLD2SKWT7S6O26OIYQPQC
OELSU5HUOEW6D2AAZJUYB5G25OOGR3YU7UZKNA57EJG5HRMCQ7UAC
V5SYTPXSEUOCYVBE3KRNZSOJMDIVOOLSOGJKQNHGZO26SHICPNCQC
JVFPF4MBNVY2UEXPWJDKTWL6RY7WCXPB6GBOK3WPJOGM6CX3D7HQC
DTOROKIMAOTTZ42ZYBWV6BBABEFW64G33UXGW334TXIG3W3MBTEAC
JCWJWGMQIKQGSSFJUQRKNIWW3HBOJSHYDTOPPE5BWOJTIJTDYUTAC
QEEJFAETO6B2J4IWDIDCJ5UNIFNNHHG22IWF2CUJRTJJBNE47CWQC
K77O2RASREWINAV465CZBBHQ2LDGRHOSEG65T5O6AZ3EUXS75XDAC
CLIEHAE2PP7ZIGLLIMYCWM4FC54KBOAN5AILOLAZJ5S26GTJM4RQC
O4ZFDG3AEV3K4NPGCCLB7DXUH5CBETKP5FBKLCIET7JNTNDX5DUAC
P2ZCF3BBG523ZEOD6XQA4X5YEHBTWH3IM33YVHXP2SQ5POXZIH4QC
J7KCPTGASQNRAKVKQ5FCXZ75E75PK7I2BB6MFSI3COWU6HRKTWSAC
TFNFP2YQA4EOVE4VIXBEQSGACZSXHWIQ2T4TIPQ46R2MJW2C4B5AC
BZMLXBTB63CXPZZPFXM4VLE7IBXPBEZ6YLM4MSNQGJR4L5IBM3OAC
I2B33Z7NZGC33AMDSSK446AZZYWKPHWLAGULVHKKZU4MVB4BNJOAC
R377SWF47GQYBJJRGPO4LB42XW3SEQAZJIRZLBQEHPVQYQFB3E2AC
S34LKQDIQJLIWVIPASOJBBZ6ZCXDHP5KPS7TRBZJSCDRVNCLK6UAC
WQ2GFFH6HN7G2LS7UGO23E6PWWT5QV2XULW6RMAYTE4SGF2HRTLAC
void drop_everything(void);
void extra_hp(int amount_extra);
bool transformation_can_wield(transformation_type trans)
{
return (trans == TRAN_NONE
|| trans == TRAN_STATUE
|| trans == TRAN_LICH);
}
bool transform_allows_wearing_item(const item_def& item)
{
return (
transform_allows_wearing_item(item,
static_cast<transformation_type>(
you.attribute[ATTR_TRANSFORMATION])));
}
case TRAN_SPIDER:
// Spiders CAN wear soft helmets
if (you.equip[EQ_HELMET] == -1
|| !is_hard_helmet(you.inv[you.equip[EQ_HELMET]]))
// Everything but bats can wear all jewellery; bats can
// only wear amulets.
if (transform == TRAN_BAT && !jewellery_is_amulet(item))
rc = false;
}
else
{
// It's not jewellery, and it's worn, so it must be armour.
const equipment_type eqslot = get_armour_slot(item);
const bool is_soft_helmet = (is_helmet(item) && !is_hard_helmet(item));
switch (transform)
case TRAN_BAT:
// Bats can't wear rings, either. This means that the only equipment
// the player may keep wearing upon transformation is an amulet.
rem_stuff.insert(EQ_LEFT_RING);
rem_stuff.insert(EQ_RIGHT_RING);
break;
// Some can't wear anything.
case TRAN_DRAGON:
case TRAN_SERPENT_OF_HELL:
case TRAN_AIR: // How did you carry it?
rc = false;
break;
case TRAN_ICE_BEAST:
rem_stuff.erase(EQ_CLOAK);
// Ice beasts CAN wear soft helmets.
if (you.equip[EQ_HELMET] == -1
|| !is_hard_helmet(you.inv[you.equip[EQ_HELMET]]))
{
rem_stuff.erase(EQ_HELMET);
}
break;
// And some need more complicated logic.
case TRAN_SPIDER:
rc = is_soft_helmet;
break;
case TRAN_LICH:
// Liches may wear anything.
rem_stuff.clear();
break;
case TRAN_BLADE_HANDS:
rc = (eqslot != EQ_SHIELD && eqslot != EQ_GLOVES);
break;
case TRAN_AIR:
// Can't wear anything at all!
rem_stuff.insert(EQ_LEFT_RING);
rem_stuff.insert(EQ_RIGHT_RING);
rem_stuff.insert(EQ_AMULET);
break;
default:
break;
default: // Bug-catcher.
mprf(MSGCH_ERROR, "Unknown transformation type %d in "
"transform_allows_wearing_item",
you.attribute[ATTR_TRANSFORMATION]);
break;
}
}
return (rc);
}
static std::set<equipment_type>
_init_equipment_removal(transformation_type trans)
{
std::set<equipment_type> result;
if (!transformation_can_wield(trans) && you.weapon())
result.insert(EQ_WEAPON);
// Liches can't wield holy weapons.
if (trans == TRAN_LICH
&& you.weapon()
&& get_weapon_brand(*you.weapon()) == SPWPN_HOLY_WRATH)
{
result.insert(EQ_WEAPON);
}
for (int i = EQ_WEAPON + 1; i < NUM_EQUIP; ++i)
{
const equipment_type eq = static_cast<equipment_type>(i);
const item_def *pitem = you.slot_item(eq);
if (pitem && !transform_allows_wearing_item(*pitem, trans))
result.insert(eq);
// Note that your weapon is handled specially, so base_type
// tells us what we need to know.
if (equip.base_type == OBJ_JEWELLERY)
jewellery_remove_effects(equip, false);
else // armour
unwear_armour( you.equip[e] );
mprf("%s %s", equip->name(DESC_CAP_YOUR).c_str(),
(unequip ? "falls away!" : "melds into your body."));
// Unmeld items in order.
std::set<equipment_type>::const_iterator iter;
for (iter = melded.begin(); iter != melded.end(); ++iter)
if (item.base_type == OBJ_JEWELLERY)
return (false);
const equipment_type eqslot = get_armour_slot(item);
if (you.mutation[MUT_HORNS] && is_hard_helmet(item))
return (true);
if (item.sub_type == ARM_BOOTS // barding excepted!
&& (you.mutation[MUT_HOOVES] || you.mutation[MUT_TALONS]))
// In case the player was mutated during the transformation,
// check whether the equipment is still wearable.
switch (e)
{
case EQ_HELMET:
if (you.mutation[MUT_HORNS] && is_hard_helmet(equip))
force_remove = true;
break;
}
case EQ_BOOTS:
if (equip.sub_type == ARM_BOOTS // i.e. not barding
&& (you.mutation[MUT_HOOVES] || you.mutation[MUT_TALONS]))
{
force_remove = true;
}
break;
if (you.equip[e] == -1)
return;
case EQ_SHIELD:
// If you switched weapons during the transformation, make
// sure you can still wear your shield.
// (This is only possible with Statue Form.)
if (you.weapon()
&& is_shield_incompatible(*you.weapon(), &equip))
{
force_remove = true;
}
break;
item_def& item = you.inv[you.equip[e]];
if (item.base_type == OBJ_JEWELLERY)
jewellery_wear_effects(item);
else
{
// In case the player was mutated during the transformation,
// check whether the equipment is still wearable.
bool force_remove = _mutations_prevent_wearing(item);
default:
break;
}
// If you switched weapons during the transformation, make
// sure you can still wear your shield.
// (This is only possible with Statue Form.)
if (e == EQ_SHIELD && you.weapon()
&& is_shield_incompatible(*you.weapon(), &item))
{
force_remove = true;
}
if (force_remove)
{
mprf("%s is pushed off your body!",
equip.name(DESC_CAP_YOUR).c_str());
you.equip[e] = -1;
}
else
armour_wear_effects(you.equip[e]);
if (force_remove)
{
mprf("%s is pushed off your body!",
item.name(DESC_CAP_YOUR).c_str());
you.equip[e] = -1;
return (true);
static void _unmeld_equipment(const std::set<equipment_type>& melded)
{
// Unmeld items in order.
std::set<equipment_type>::const_iterator iter;
for (iter = melded.begin(); iter != melded.end(); ++iter)
{
const equipment_type e = *iter;
if (e == EQ_WEAPON || you.equip[e] == -1)
continue;
_rewear_equipment_slot(e);
}
// We drop everything except jewellery by default.
const equipment_type default_rem[] = {
EQ_WEAPON, EQ_CLOAK, EQ_HELMET, EQ_GLOVES, EQ_BOOTS,
EQ_SHIELD, EQ_BODY_ARMOUR
};
std::set<equipment_type> rem_stuff(default_rem,
default_rem + ARRAYSZ(default_rem));
_init_equipment_removal(rem_stuff, which_trans);
you.redraw_evasion = true;
you.redraw_armour_class = true;
you.wield_change = true;
std::set<equipment_type> rem_stuff = _init_equipment_removal(which_trans);
if (_check_for_cursed_equipment(rem_stuff, which_trans, quiet))
return (false);
case TRAN_SPIDER: // also AC +3, ev +3, fast_run
if (_check_for_cursed_equipment(rem_stuff, which_trans, quiet))
return (false);
case TRAN_SPIDER:
tran_name = "spider";
dex = 5;
symbol = 's';
colour = BROWN;
dur = std::min(10 + random2(pow) + random2(pow), 60);
msg = "You turn into a venomous arachnid creature.";
break;
// Check in case we'll auto-remove stat boosting equipment.
if (check_transformation_stat_loss(rem_stuff, quiet))
return (false);
case TRAN_BLADE_HANDS:
tran_name = "Blade Hands";
dur = std::min(10 + random2(pow), 100);
msg = "Your hands turn into razor-sharp scythe blades.";
break;
mpr("You turn into a venomous arachnid creature.");
_remove_equipment(rem_stuff);
case TRAN_STATUE:
tran_name = "statue";
str = 2;
dex = -2;
xhp = 15;
symbol = '8';
colour = LIGHTGREY;
dur = std::min(20 + random2(pow) + random2(pow), 100);
if (you.species == SP_GNOME && coinflip())
msg = "Look, a garden gnome. How cute!";
else if (player_genus(GENPC_DWARVEN) && one_chance_in(10))
msg = "You inwardly fear your resemblance to a lawn ornament.";
else
msg = "You turn into a living statue of rough stone.";
break;
you.attribute[ATTR_TRANSFORMATION] = TRAN_SPIDER;
you.duration[DUR_TRANSFORMATION] = 10 + random2(pow) + random2(pow);
case TRAN_ICE_BEAST:
tran_name = "ice beast";
xhp = 12;
symbol = 'I';
colour = WHITE;
dur = std::min(30 + random2(pow) + random2(pow), 100);
msg = "You turn into a creature of crystalline ice.";
break;
if (you.duration[DUR_TRANSFORMATION] > 60)
you.duration[DUR_TRANSFORMATION] = 60;
case TRAN_DRAGON:
tran_name = "dragon";
str = 10;
xhp = 16;
symbol = 'D';
colour = GREEN;
dur = std::min(20 + random2(pow) + random2(pow), 100);
if (you.species == SP_MERFOLK && player_is_swimming())
{
msg = "You fly out of the water as you turn into "
"a fearsome dragon!";
}
else
msg = "You turn into a fearsome dragon!";
break;
modify_stat( STAT_DEXTERITY, 5, true,
"gaining the spider transformation");
case TRAN_LICH:
tran_name = "lich";
str = 3;
symbol = 'L';
colour = LIGHTGREY;
dur = std::min(20 + random2(pow) + random2(pow), 100);
msg = "Your body is suffused with negative energy!";
break;
you.symbol = 's';
you.colour = BROWN;
case TRAN_SERPENT_OF_HELL:
tran_name = "Serpent of Hell";
str = 13;
xhp = 17;
symbol = 'S';
colour = RED;
dur = std::min(20 + random2(pow) + random2(pow), 120);
msg = "You transform into a huge demonic serpent!";
break;
_transformation_expiration_warning();
return (true);
case TRAN_AIR:
tran_name = "air";
dex = 8;
symbol = '#';
colour = DARKGREY;
dur = std::min(35 + random2(pow) + random2(pow), 150);
msg = "You feel diffuse...";
break;
if (_check_for_cursed_equipment(rem_stuff, which_trans, quiet))
return (false);
if (check_transformation_stat_loss(rem_stuff, quiet, 5)) // Str loss = 5
return (false);
mprf("You turn into a %sbat.",
you.species == SP_VAMPIRE ? "vampire " : "");
_remove_equipment(rem_stuff);
you.attribute[ATTR_TRANSFORMATION] = TRAN_BAT;
you.duration[DUR_TRANSFORMATION] = 20 + random2(pow) + random2(pow);
if (you.duration[DUR_TRANSFORMATION] > 100)
you.duration[DUR_TRANSFORMATION] = 100;
// high ev, low ac, high speed
modify_stat( STAT_DEXTERITY, 5, true,
"gaining the bat transformation");
modify_stat( STAT_STRENGTH, -5, true,
"gaining the bat transformation" );
you.symbol = 'b';
you.colour = (you.species == SP_VAMPIRE ? DARKGREY : LIGHTGREY);
if (you.species != SP_VAMPIRE)
_transformation_expiration_warning();
return (true);
case TRAN_ICE_BEAST: // also AC +3, cold +3, fire -1, pois +1
if (_check_for_cursed_equipment(rem_stuff, which_trans, quiet))
return (false);
// Check in case we'll auto-remove stat boosting equipment.
if (check_transformation_stat_loss(rem_stuff, quiet))
return (false);
tran_name = "bat";
str = -5;
dex = 5;
symbol = 'b';
colour = (you.species == SP_VAMPIRE ? DARKGREY : LIGHTGREY);
dur = std::min(20 + random2(pow) + random2(pow), 100);
if (you.species == SP_VAMPIRE)
msg = "You turn into a vampire bat.";
else
msg = "You turn into a bat.";
break;
you.attribute[ATTR_TRANSFORMATION] = TRAN_ICE_BEAST;
you.duration[DUR_TRANSFORMATION] = 30 + random2(pow) + random2(pow);
// All checks done, transformation will take place now.
you.redraw_evasion = true;
you.redraw_armour_class = true;
you.wield_change = true;
if (you.duration[ DUR_TRANSFORMATION ] > 100)
you.duration[ DUR_TRANSFORMATION ] = 100;
// Most transformations conflict with stone skin.
if (which_trans != TRAN_NONE
&& which_trans != TRAN_BLADE_HANDS
&& which_trans != TRAN_STATUE)
{
you.duration[DUR_STONESKIN] = 0;
}
you.symbol = 'I';
you.colour = WHITE;
_transformation_expiration_warning();
return (true);
case TRAN_BLADE_HANDS:
if (_check_for_cursed_equipment(rem_stuff, which_trans, quiet))
return (false);
// Check in case we'll auto-remove stat boosting equipment.
if (check_transformation_stat_loss(rem_stuff, quiet))
return (false);
mpr("Your hands turn into razor-sharp scythe blades.");
_remove_equipment(rem_stuff);
you.attribute[ATTR_TRANSFORMATION] = TRAN_BLADE_HANDS;
you.duration[DUR_TRANSFORMATION] = 10 + random2(pow);
if (you.duration[ DUR_TRANSFORMATION ] > 100)
you.duration[ DUR_TRANSFORMATION ] = 100;
_transformation_expiration_warning();
return (true);
case TRAN_STATUE: // also AC +20, ev -5, elec +1, pois +1, neg +1, slow
if (_check_for_cursed_equipment(rem_stuff, which_trans, quiet))
return (false);
// Lose 2 dex
if (check_transformation_stat_loss(rem_stuff, quiet, 0, 2))
return (false);
if (you.species == SP_GNOME && coinflip())
mpr("Look, a garden gnome. How cute!");
else if (player_genus(GENPC_DWARVEN) && one_chance_in(10))
mpr("You inwardly fear your resemblance to a lawn ornament.");
else
mpr("You turn into a living statue of rough stone.");
// Too stiff to make use of shields, gloves, or armour -- bwr
_remove_equipment(rem_stuff);
// Update your status.
you.attribute[ATTR_TRANSFORMATION] = which_trans;
you.duration[DUR_TRANSFORMATION] = dur;
you.symbol = symbol;
you.colour = colour;
modify_stat( STAT_DEXTERITY, -2, true,
"gaining the statue transformation" );
modify_stat( STAT_STRENGTH, 2, true,
"gaining the statue transformation");
extra_hp(15); // must occur after attribute set
if (xhp)
_extra_hp(xhp);
you.symbol = '8';
you.colour = LIGHTGREY;
_transformation_expiration_warning();
return (true);
case TRAN_DRAGON: // also AC +10, ev -3, cold -1, fire +2, pois +1, flight
if (_check_for_cursed_equipment(rem_stuff, which_trans, quiet))
return (false);
// Check in case we'll auto-remove stat boosting equipment.
if (check_transformation_stat_loss(rem_stuff, quiet))
return (false);
if (you.species == SP_MERFOLK && player_is_swimming())
{
mpr("You fly out of the water as you turn into "
"a fearsome dragon!");
}
else
mpr("You turn into a fearsome dragon!");
case TRAN_ICE_BEAST:
if (you.duration[DUR_ICY_ARMOUR])
mpr("Your new body merges with your icy armour.");
break;
_remove_equipment(rem_stuff);
you.attribute[ATTR_TRANSFORMATION] = TRAN_DRAGON;
you.duration[DUR_TRANSFORMATION] = 20 + random2(pow) + random2(pow);
if (you.duration[ DUR_TRANSFORMATION ] > 100)
you.duration[ DUR_TRANSFORMATION ] = 100;
modify_stat( STAT_STRENGTH, 10, true,
"gaining the dragon transformation" );
extra_hp(16); // must occur after attribute set
you.symbol = 'D';
you.colour = GREEN;
case TRAN_DRAGON:
// AC +3, cold +1, neg +3, pois +1, is_undead, res magic +50,
// spec_death +1, and drain attack (if empty-handed)
if (you.duration[DUR_DEATHS_DOOR])
{
if (!quiet)
{
mpr( "The transformation conflicts with an enchantment "
"already in effect." );
}
return (false);
}
// Remove holy wrath weapons if necessary.
if (you.weapon()
&& get_weapon_brand(*you.weapon()) == SPWPN_HOLY_WRATH)
{
rem_stuff.insert(EQ_WEAPON);
}
if (_check_for_cursed_equipment(rem_stuff, which_trans, quiet))
return (false);
if (check_transformation_stat_loss(rem_stuff, quiet))
return (false);
mpr("Your body is suffused with negative energy!");
_remove_equipment(rem_stuff);
you.attribute[ATTR_TRANSFORMATION] = TRAN_LICH;
you.duration[DUR_TRANSFORMATION] = 20 + random2(pow) + random2(pow);
if (you.duration[ DUR_TRANSFORMATION ] > 100)
you.duration[ DUR_TRANSFORMATION ] = 100;
modify_stat( STAT_STRENGTH, 3, true,
"gaining the lich transformation" );
you.symbol = 'L';
you.colour = LIGHTGREY;
if (_check_for_cursed_equipment(rem_stuff, which_trans, quiet))
return (false);
// Check in case we'll auto-remove stat boosting equipment.
if (check_transformation_stat_loss(rem_stuff, quiet))
return (false);
_drop_everything();
// also AC 20, ev +20, regen/2, no hunger, fire -2, cold -2, air +2,
// pois +1, spec_earth -1
mpr("You feel diffuse...");
_remove_equipment(rem_stuff);
drop_everything();
you.attribute[ATTR_TRANSFORMATION] = TRAN_AIR;
you.duration[DUR_TRANSFORMATION] = 35 + random2(pow) + random2(pow);
if (you.duration[ DUR_TRANSFORMATION ] > 150)
you.duration[ DUR_TRANSFORMATION ] = 150;
modify_stat( STAT_DEXTERITY, 8, true,
"gaining the air transformation" );
you.symbol = '#';
you.colour = DARKGREY;
_transformation_expiration_warning();
return (true);
case TRAN_SERPENT_OF_HELL:
if (_check_for_cursed_equipment(rem_stuff, which_trans, quiet))
return (false);
// Check in case we'll auto-remove stat boosting equipment.
if (check_transformation_stat_loss(rem_stuff, quiet))
return (false);
// also AC +10, ev -5, fire +2, pois +1, life +2, slow
mpr("You transform into a huge demonic serpent!");
_remove_equipment(rem_stuff);
you.attribute[ATTR_TRANSFORMATION] = TRAN_SERPENT_OF_HELL;
you.duration[DUR_TRANSFORMATION] = 20 + random2(pow) + random2(pow);
if (you.duration[ DUR_TRANSFORMATION ] > 120)
you.duration[ DUR_TRANSFORMATION ] = 120;
modify_stat( STAT_STRENGTH, 13, true,
"gaining the Serpent of Hell transformation");
extra_hp(17); // must occur after attribute set
you.symbol = 'S';
you.colour = RED;
default:
break;
}
return (true);
case TRAN_NONE:
case NUM_TRANSFORMATIONS:
break;
}
const equipment_type default_rem[] = {
EQ_CLOAK, EQ_HELMET, EQ_GLOVES, EQ_BOOTS, EQ_SHIELD, EQ_BODY_ARMOUR
};
std::set<equipment_type> melded(default_rem,
default_rem + ARRAYSZ(default_rem));
_init_equipment_removal(melded, old_form);
std::set<equipment_type> melded = _init_equipment_removal(old_form);