diff options
author | peterb12 <peterb12@c06c8d41-db1a-0410-9941-cceddc491573> | 2005-07-21 02:34:44 +0000 |
---|---|---|
committer | peterb12 <peterb12@c06c8d41-db1a-0410-9941-cceddc491573> | 2005-07-21 02:34:44 +0000 |
commit | 673bdae75485d14f759af597c3c62b99601f9a43 (patch) | |
tree | 368103f29fe0ce5dcf98060d9b5faa04590085fb /trunk/source/transfor.cc | |
parent | 7e900be770db24b0405fd2162491c405a425873e (diff) | |
download | crawl-ref-673bdae75485d14f759af597c3c62b99601f9a43.tar.gz crawl-ref-673bdae75485d14f759af597c3c62b99601f9a43.zip |
Initial revision
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'trunk/source/transfor.cc')
-rw-r--r-- | trunk/source/transfor.cc | 551 |
1 files changed, 551 insertions, 0 deletions
diff --git a/trunk/source/transfor.cc b/trunk/source/transfor.cc new file mode 100644 index 0000000000..9ee38d548d --- /dev/null +++ b/trunk/source/transfor.cc @@ -0,0 +1,551 @@ +/* + * File: transfor.cc + * Summary: Misc function related to player transformations. + * Written by: Linley Henzell + * + * Change History (most recent first): + * + * <2> 5/26/99 JDJ transform() and untransform() set you.wield_change so + * the weapon line updates. + * <1> -/--/-- LRH Created + */ + +#include "AppHdr.h" +#include "transfor.h" + +#include <stdio.h> +#include <string.h> + +#include "externs.h" + +#include "it_use2.h" +#include "itemname.h" +#include "items.h" +#include "misc.h" +#include "player.h" +#include "skills2.h" +#include "stuff.h" + +extern unsigned char your_sign; // defined in view.cc +extern unsigned char your_colour; // defined in view.cc +void drop_everything(void); +void extra_hp(int amount_extra); + +bool remove_equipment(FixedVector < char, 8 > &remove_stuff) +{ + char str_pass[ ITEMNAME_SIZE ]; + + // if we're removing body armour, the cloak will come off as well -- bwr + if (remove_stuff[EQ_BODY_ARMOUR] == 1 && you.equip[EQ_BODY_ARMOUR] != -1) + remove_stuff[EQ_CLOAK] = 1; + + // if we're removing gloves, the weapon will come off as well -- bwr + if (remove_stuff[EQ_GLOVES] == 1 && you.equip[EQ_GLOVES] != -1) + remove_stuff[EQ_WEAPON] = 1; + + if (remove_stuff[EQ_WEAPON] == 1 && you.equip[EQ_WEAPON] != -1) + { + unwield_item(you.equip[EQ_WEAPON]); + you.equip[EQ_WEAPON] = -1; + mpr("You are empty-handed."); + you.wield_change = true; + } + + for (int i = EQ_CLOAK; i < EQ_LEFT_RING; i++) + { + if (remove_stuff[i] == 0 || you.equip[i] == -1) + continue; + + in_name( you.equip[i], DESC_CAP_YOUR, str_pass ); + + snprintf( info, INFO_SIZE, "%s falls away.", str_pass ); + mpr(info); + + unwear_armour( you.equip[i] ); + you.equip[i] = -1; + } + + return true; +} // end remove_equipment() + +// Returns true if any piece of equipment that has to be removed is cursed. +// Useful for keeping low level transformations from being too useful. +static bool check_for_cursed_equipment( FixedVector < char, 8 > &remove_stuff ) +{ + for (int i = EQ_WEAPON; i < EQ_LEFT_RING; i++) + { + if (remove_stuff[i] == 0 || you.equip[i] == -1) + continue; + + if (item_cursed( you.inv[ you.equip[i] ] )) + { + mpr( "Your cursed equipment won't allow you to complete the " + "transformation." ); + + return (true); + } + } + + return (false); +} // end check_for_cursed_equipment() + +bool transform(int pow, char which_trans) +{ + if (you.species == SP_MERFOLK && player_is_swimming() + && which_trans != TRAN_DRAGON) + { + // This might by overkill, but it's okay because obviously + // whatever magical ability that let's them walk on land is + // removed when they're in water (in this case, their natural + // form is completely over-riding any other... goes well with + // the forced transform when entering water)... but merfolk can + // transform into dragons, because dragons fly. -- bwr + mpr("You cannot transform out of your normal form while in water."); + return (false); + } + + // This must occur before the untransform() and the is_undead check. + if (you.attribute[ATTR_TRANSFORMATION] == which_trans) + { + if (you.duration[DUR_TRANSFORMATION] < 100) + { + mpr( "You extend your transformation's duration." ); + you.duration[DUR_TRANSFORMATION] += random2(pow); + + if (you.duration[DUR_TRANSFORMATION] > 100) + you.duration[DUR_TRANSFORMATION] = 100; + + return (true); + } + else + { + mpr( "You cannot extend your transformation any further!" ); + return (false); + } + } + + if (you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE) + untransform(); + + if (you.is_undead) + { + mpr("Your unliving flesh cannot be transformed in this way."); + return (false); + } + + //jmf: silently discard this enchantment + you.duration[DUR_STONESKIN] = 0; + + FixedVector < char, 8 > rem_stuff; + + for (int i = EQ_WEAPON; i < EQ_RIGHT_RING; i++) + rem_stuff[i] = 1; + + you.redraw_evasion = 1; + you.redraw_armour_class = 1; + you.wield_change = true; + + /* Remember, it can still fail in the switch below... */ + switch (which_trans) + { + case TRAN_SPIDER: // also AC +3, ev +3, fast_run + if (check_for_cursed_equipment( rem_stuff )) + return (false); + + mpr("You turn into a venomous arachnid creature."); + remove_equipment( rem_stuff ); + + you.attribute[ATTR_TRANSFORMATION] = TRAN_SPIDER; + you.duration[DUR_TRANSFORMATION] = 10 + random2(pow) + random2(pow); + + if (you.duration[DUR_TRANSFORMATION] > 60) + you.duration[DUR_TRANSFORMATION] = 60; + + modify_stat( STAT_DEXTERITY, 5, true ); + + your_sign = 's'; + your_colour = BROWN; + return (true); + + case TRAN_ICE_BEAST: // also AC +3, cold +3, fire -1, pois +1 + mpr( "You turn into a creature of crystalline ice." ); + + rem_stuff[ EQ_CLOAK ] = 0; + + remove_equipment( rem_stuff ); + + you.attribute[ATTR_TRANSFORMATION] = TRAN_ICE_BEAST; + you.duration[DUR_TRANSFORMATION] = 30 + random2(pow) + random2(pow); + + if (you.duration[ DUR_TRANSFORMATION ] > 100) + you.duration[ DUR_TRANSFORMATION ] = 100; + + extra_hp(12); // must occur after attribute set + + if (you.duration[DUR_ICY_ARMOUR]) + mpr( "Your new body merges with your icy armour." ); + + your_sign = 'I'; + your_colour = WHITE; + return (true); + + case TRAN_BLADE_HANDS: + rem_stuff[EQ_CLOAK] = 0; + rem_stuff[EQ_HELMET] = 0; + rem_stuff[EQ_BOOTS] = 0; + rem_stuff[EQ_BODY_ARMOUR] = 0; + + if (check_for_cursed_equipment( rem_stuff )) + 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; + return (true); + + case TRAN_STATUE: // also AC +20, ev -5, elec +1, pois +1, neg +1, slow + 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." ); + + rem_stuff[ EQ_WEAPON ] = 0; /* can still hold a weapon */ + rem_stuff[ EQ_CLOAK ] = 0; + rem_stuff[ EQ_HELMET ] = 0; + rem_stuff[ EQ_BOOTS ] = 0; + // too stiff to make use of shields, gloves, or armour -- bwr + + remove_equipment( rem_stuff ); + + you.attribute[ATTR_TRANSFORMATION] = TRAN_STATUE; + you.duration[DUR_TRANSFORMATION] = 20 + random2(pow) + random2(pow); + + if (you.duration[ DUR_TRANSFORMATION ] > 100) + you.duration[ DUR_TRANSFORMATION ] = 100; + + modify_stat( STAT_DEXTERITY, -2, true ); + modify_stat( STAT_STRENGTH, 2, true ); + extra_hp(15); // must occur after attribute set + + if (you.duration[DUR_STONEMAIL] || you.duration[DUR_STONESKIN]) + mpr( "Your new body merges with your stone armour." ); + + your_sign = '8'; + your_colour = LIGHTGREY; + return (true); + + case TRAN_DRAGON: // also AC +10, ev -3, cold -1, fire +2, pois +1, flight + 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!"); + + 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 ); + extra_hp(16); // must occur after attribute set + + your_sign = 'D'; + your_colour = GREEN; + return (true); + + case TRAN_LICH: + // also AC +3, cold +1, neg +3, pois +1, is_undead, res magic +50, + // spec_death +1, and drain attack (if empty-handed) + if (you.deaths_door) + { + mpr( "The transformation conflicts with an enchantment " + "already in effect." ); + + return (false); + } + + mpr("Your body is suffused with negative energy!"); + + // undead cannot regenerate -- bwr + if (you.duration[DUR_REGENERATION]) + { + mpr( "You stop regenerating.", MSGCH_DURATION ); + you.duration[DUR_REGENERATION] = 0; + } + + // silently removed since undead automatically resist poison -- bwr + you.duration[DUR_RESIST_POISON] = 0; + + /* no remove_equip */ + 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 ); + your_sign = 'L'; + your_colour = LIGHTGREY; + you.is_undead = US_UNDEAD; + you.hunger_state = HS_SATIATED; // no hunger effects while transformed + set_redraw_status( REDRAW_HUNGER ); + return (true); + + case TRAN_AIR: + // 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 ); + your_sign = '#'; + your_colour = DARKGREY; + return (true); + + case TRAN_SERPENT_OF_HELL: + // 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 ); + extra_hp(17); // must occur after attribute set + + your_sign = 'S'; + your_colour = RED; + return (true); + } + + return (false); +} // end transform() + +void untransform(void) +{ + FixedVector < char, 8 > rem_stuff; + + for (int i = EQ_WEAPON; i < EQ_RIGHT_RING; i++) + rem_stuff[i] = 0; + + you.redraw_evasion = 1; + you.redraw_armour_class = 1; + you.wield_change = true; + + your_sign = '@'; + your_colour = LIGHTGREY; + + // must be unset first or else infinite loops might result -- bwr + const int old_form = you.attribute[ ATTR_TRANSFORMATION ]; + you.attribute[ ATTR_TRANSFORMATION ] = TRAN_NONE; + you.duration[ DUR_TRANSFORMATION ] = 0; + + switch (old_form) + { + case TRAN_SPIDER: + mpr("Your transformation has ended.", MSGCH_DURATION); + modify_stat( STAT_DEXTERITY, -5, true ); + break; + + case TRAN_BLADE_HANDS: + mpr( "Your hands revert to their normal proportions.", MSGCH_DURATION ); + you.wield_change = true; + break; + + case TRAN_STATUE: + mpr( "You revert to your normal fleshy form.", MSGCH_DURATION ); + modify_stat( STAT_DEXTERITY, 2, true ); + modify_stat( STAT_STRENGTH, -2, true ); + + // Note: if the core goes down, the combined effect soon disappears, + // but the reverse isn't true. -- bwr + if (you.duration[DUR_STONEMAIL]) + you.duration[DUR_STONEMAIL] = 1; + + if (you.duration[DUR_STONESKIN]) + you.duration[DUR_STONESKIN] = 1; + break; + + case TRAN_ICE_BEAST: + mpr( "You warm up again.", MSGCH_DURATION ); + + // Note: if the core goes down, the combined effect soon disappears, + // but the reverse isn't true. -- bwr + if (you.duration[DUR_ICY_ARMOUR]) + you.duration[DUR_ICY_ARMOUR] = 1; + break; + + case TRAN_DRAGON: + mpr( "Your transformation has ended.", MSGCH_DURATION ); + modify_stat(STAT_STRENGTH, -10, true); + + if (!player_is_levitating() + && (grd[you.x_pos][you.y_pos] == DNGN_LAVA + || grd[you.x_pos][you.y_pos] == DNGN_DEEP_WATER + || grd[you.x_pos][you.y_pos] == DNGN_SHALLOW_WATER)) + { + if (you.species == SP_MERFOLK + && grd[you.x_pos][you.y_pos] != DNGN_LAVA) + { + mpr("You dive into the water and return to your normal form."); + merfolk_start_swimming(); + } + + if (grd[you.x_pos][you.y_pos] != DNGN_SHALLOW_WATER) + fall_into_a_pool( true, grd[you.x_pos][you.y_pos] ); + } + break; + + case TRAN_LICH: + mpr( "You feel yourself come back to life.", MSGCH_DURATION ); + modify_stat(STAT_STRENGTH, -3, true); + you.is_undead = US_ALIVE; + break; + + case TRAN_AIR: + mpr( "Your body solidifies.", MSGCH_DURATION ); + modify_stat(STAT_DEXTERITY, -8, true); + break; + + case TRAN_SERPENT_OF_HELL: + mpr( "Your transformation has ended.", MSGCH_DURATION ); + modify_stat(STAT_STRENGTH, -13, true); + break; + } + + // If nagas wear boots while transformed, they fall off again afterwards: + // I don't believe this is currently possible, and if it is we + // probably need something better to cover all possibilities. -bwr + if ((you.species == SP_NAGA || you.species == SP_CENTAUR) + && you.equip[ EQ_BOOTS ] != -1 + && you.inv[ you.equip[EQ_BOOTS] ].plus2 != TBOOT_NAGA_BARDING) + { + rem_stuff[EQ_BOOTS] = 1; + remove_equipment(rem_stuff); + } + + calc_hp(); +} // end untransform() + +// XXX: This whole system is a mess as it still relies on special +// cases to handle a large number of things (see wear_armour()) -- bwr +bool can_equip( char use_which ) +{ + + // if more cases are added to this if must also change in + // item_use for naga barding + if (!player_is_shapechanged()) + /* or a transformation which doesn't change overall shape */ + { + if (use_which == EQ_BOOTS) + { + switch (you.species) + { + case SP_NAGA: + case SP_CENTAUR: + case SP_KENKU: + return (false); + default: + break; + } + } + else if (use_which == EQ_HELMET) + { + switch (you.species) + { + case SP_MINOTAUR: + case SP_KENKU: + return (false); + default: + break; + } + } + } + + if (use_which == EQ_HELMET && you.mutation[MUT_HORNS]) + return (false); + + if (use_which == EQ_BOOTS && you.mutation[MUT_HOOVES]) + return (false); + + if (use_which == EQ_GLOVES && you.mutation[MUT_CLAWS] >= 3) + return (false); + + switch (you.attribute[ATTR_TRANSFORMATION]) + { + case TRAN_NONE: + case TRAN_LICH: + return (true); + + case TRAN_BLADE_HANDS: + return (use_which != EQ_WEAPON + && use_which != EQ_GLOVES + && use_which != EQ_SHIELD); + + case TRAN_STATUE: + return (use_which == EQ_WEAPON + || use_which == EQ_CLOAK + || use_which == EQ_HELMET); + + case TRAN_ICE_BEAST: + return (use_which == EQ_CLOAK); + + default: + return (false); + } + + return (true); +} // end can_equip() + +void extra_hp(int amount_extra) // must also set in calc_hp +{ + calc_hp(); + + you.hp *= amount_extra; + you.hp /= 10; + + deflate_hp(you.hp_max, false); +} // end extra_hp() + +void drop_everything(void) +{ + int i = 0; + + if (inv_count() < 1) + return; + + mpr( "You find yourself unable to carry your possessions!" ); + + for (i = 0; i < ENDOFPACK; i++) + { + if (is_valid_item( you.inv[i] )) + { + copy_item_to_grid( you.inv[i], you.x_pos, you.y_pos ); + you.inv[i].quantity = 0; + } + } + + return; +} // end drop_everything() |