From cb371dc5d4f25044434fe5b632a769abf5b949ad Mon Sep 17 00:00:00 2001 From: j-p-e-g Date: Mon, 14 Apr 2008 23:15:33 +0000 Subject: Bug 1941782: Allow vampires to learn spells such as Berserk and Transmigrations, but let them only cast them while full or more. (Once satiated is reached, they automatically time out.) Bug 1941885: Don't give vampires nutrition from quaffing non-blood potions. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@4235 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/enum.h | 57 ++++++------ crawl-ref/source/food.cc | 110 +++++++++++++--------- crawl-ref/source/item_use.cc | 3 +- crawl-ref/source/newgame.cc | 3 +- crawl-ref/source/spl-book.cc | 19 +++- crawl-ref/source/spl-cast.cc | 217 +++++++++++++++++++++++++------------------ crawl-ref/source/transfor.cc | 54 +++++------ 7 files changed, 269 insertions(+), 194 deletions(-) diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index ed02e21851..9e6b47ad58 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -158,7 +158,7 @@ enum actor_type ACT_PLAYER, ACT_MONSTER }; - + enum attribute_type { ATTR_DIVINE_LIGHTNING_PROTECTION, // 0 @@ -193,7 +193,7 @@ enum quiver_type enum beam_type // beam[].flavour { BEAM_NONE, // 0 - + BEAM_MISSILE, BEAM_MMISSILE, // and similarly irresistible things BEAM_FIRE, @@ -379,7 +379,7 @@ enum char_set_type NUM_CSET }; -enum cloud_type +enum cloud_type { CLOUD_NONE, CLOUD_FIRE, @@ -501,7 +501,7 @@ enum command_type CMD_RESISTS_SCREEN, CMD_READ_MESSAGES, - + CMD_MOUSE_MOVE, CMD_MOUSE_CLICK, @@ -608,7 +608,7 @@ enum command_type // Disable/enable -more- prompts. CMD_DISABLE_MORE, CMD_ENABLE_MORE, - + // [ds] Silently ignored, requests another round of input. CMD_NEXT_CMD, @@ -694,8 +694,8 @@ enum startup_book_type // happen. enum delay_type { - DELAY_NOT_DELAYED, - DELAY_EAT, + DELAY_NOT_DELAYED, + DELAY_EAT, DELAY_ARMOUR_ON, DELAY_ARMOUR_OFF, DELAY_JEWELLERY_ON, @@ -814,12 +814,12 @@ enum dungeon_char_type DCHAR_FIRED_ARMOUR, DCHAR_FIRED_MISSILE, DCHAR_EXPLOSION, - + NUM_DCHAR_TYPES }; // When adding: -// +// // * New stairs/portals: update grid_stair_direction. // * Any: edit view.cc and add a glyph and colour for the feature. // * Any: edit direct.cc and add a description for the feature. @@ -1393,7 +1393,7 @@ enum map_marker_type enum menu_type { MT_ANY = -1, - + MT_INVLIST, // List inventory MT_DROP, @@ -1412,7 +1412,7 @@ enum mon_holy_type enum targ_mode_type { - TARG_ANY, + TARG_ANY, TARG_ENEMY, TARG_FRIEND, TARG_NUM_MODES @@ -1726,13 +1726,13 @@ enum monster_type // (int) menv[].type // Sync up with monplace.cc's draconian selection if adding more. MONS_DRACONIAN_CALLER, - MONS_DRACONIAN_MONK, + MONS_DRACONIAN_MONK, MONS_DRACONIAN_ZEALOT, MONS_DRACONIAN_SHIFTER, MONS_DRACONIAN_ANNIHILATOR, // 325 MONS_DRACONIAN_KNIGHT, MONS_DRACONIAN_SCORCHER, - + MONS_MURRAY, MONS_TIAMAT, @@ -1825,13 +1825,13 @@ enum monster_type // (int) menv[].type // A random draconian, either base coloured drac or specialised. RANDOM_DRACONIAN, - + // Any random base draconian colour. RANDOM_BASE_DRACONIAN, // Any random specialised draconian, such as a draconian knight. RANDOM_NONBASE_DRACONIAN, - + WANDERING_MONSTER = 2500 // only used in monster placement routines - forced limit checks {dlb} }; @@ -2077,7 +2077,7 @@ enum mutation_type MUT_THROW_FLAMES, // 55 MUT_THROW_FROST, MUT_SMITE, - MUT_CLAWS, + MUT_CLAWS, MUT_FANGS, // new in 0.3 // hooves and talons can replace feet MUT_HOOVES, // 60 @@ -2091,7 +2091,7 @@ enum mutation_type MUT_SHAGGY_FUR, // new in 0.4 MUT_HIGH_MAGIC, // new in 0.4 MUT_LOW_MAGIC, // new in 0.4 -- 70 - + // several types of scales (affect AC and sometimes more) MUT_RED_SCALES = 75, // 75 MUT_NACREOUS_SCALES, @@ -2253,7 +2253,7 @@ enum size_type SIZE_MEDIUM, // human/elf/dwarf SIZE_LARGE, // troll/ogre/centaur/naga SIZE_BIG, // large quadrupeds - SIZE_GIANT, // giant + SIZE_GIANT, // giant SIZE_HUGE, // dragon NUM_SIZE_LEVELS, SIZE_CHARACTER // transformations that don't change size @@ -2343,12 +2343,12 @@ enum species_type SP_MOTTLED_DRACONIAN, SP_PALE_DRACONIAN, SP_BASE_DRACONIAN, // 25 - SP_CENTAUR, + SP_CENTAUR, SP_DEMIGOD, - SP_SPRIGGAN, + SP_SPRIGGAN, SP_MINOTAUR, SP_DEMONSPAWN, // 30 - SP_GHOUL, + SP_GHOUL, SP_KENKU, SP_MERFOLK, SP_VAMPIRE, // 34 @@ -2654,14 +2654,14 @@ enum tutorial_event_type TUT_SEEN_STAIRS, // 14 TUT_SEEN_ESCAPE_HATCH, TUT_SEEN_TRAP, - TUT_SEEN_ALTAR, - TUT_SEEN_SHOP, + TUT_SEEN_ALTAR, + TUT_SEEN_SHOP, TUT_SEEN_DOOR, // other 'first events' TUT_SEEN_MONSTER, // 20 TUT_MONSTER_BRAND, TUT_KILLED_MONSTER, - TUT_NEW_LEVEL, + TUT_NEW_LEVEL, TUT_SKILL_RAISE, TUT_MAKE_CHUNKS, // 25 TUT_OFFER_CORPSE, @@ -2698,13 +2698,14 @@ enum tutorial_types TUT_MAGIC_CHAR, TUT_RANGER_CHAR, TUT_TYPES_NUM // 3 -}; +}; enum undead_state_type // you.is_undead { US_ALIVE = 0, - US_HUNGRY_DEAD, - US_UNDEAD + US_HUNGRY_DEAD, // Ghouls + US_UNDEAD, // Mummies + US_SEMI_UNDEAD // Vampires }; enum unique_item_status_type @@ -2723,6 +2724,6 @@ enum wizard_option_type WIZ_YES // start character in wiz mode }; -#endif +#endif #endif // ENUM_H diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc index 77be3d333a..962da54dbe 100644 --- a/crawl-ref/source/food.cc +++ b/crawl-ref/source/food.cc @@ -145,7 +145,7 @@ void weapon_switch( int targ ) // XXX This is a pretty dangerous hack; I don't like it.--GDL // // Well yeah, but that's because interacting with the wielding - // code is a mess... this whole function's purpose was to + // code is a mess... this whole function's purpose was to // isolate this hack until there's a proper way to do things. -- bwr if (you.equip[EQ_WEAPON] != -1) unwield_item(false); @@ -176,7 +176,7 @@ static bool find_butchering_implement( bool fallback ) return false; } } - + // look for a butchering implement in your pack for (int i = 0; i < ENDOFPACK; ++i) { @@ -201,12 +201,12 @@ static bool find_butchering_implement( bool fallback ) // if we didn't swap above, then we still can't cut...let's call // wield_weapon() in the "prompt the user" way... - + // prompt for new weapon int old_weapon = you.equip[EQ_WEAPON]; mpr( "What would you like to use?", MSGCH_PROMPT ); wield_weapon( false ); - + // let's see if the user did something... return (you.equip[EQ_WEAPON] != old_weapon); } @@ -274,7 +274,7 @@ bool butchery(int which_corpse) { corpse_id = o; num_corpses++; - + // return pre-chosen corpse if it exists if (prechosen && corpse_id == which_corpse) break; @@ -285,7 +285,7 @@ bool butchery(int which_corpse) prechosen = false; bool canceled_butcher = false; - + // Now pick what you want to butcher. This is only a problem // if there are several corpses on the square. if ( num_corpses == 0 ) @@ -304,12 +304,12 @@ bool butchery(int which_corpse) if ( (mitm[o].base_type != OBJ_CORPSES) || (mitm[o].sub_type != CORPSE_BODY) ) continue; - + // offer the possibility of butchering snprintf(info, INFO_SIZE, "%s %s?", can_bottle_blood_from_corpse(mitm[o].plus)? "Bottle" : "Butcher", mitm[o].name(DESC_NOCAP_A).c_str()); - + const int result = yesnoquit(info, true, 'N', false, 'C', 'D'); if ( result == -1 ) { @@ -325,7 +325,7 @@ bool butchery(int which_corpse) // continue loop for 0 } } - + // Do the actual butchery, if we found a good corpse. if ( corpse_id != -1 ) { @@ -333,7 +333,7 @@ bool butchery(int which_corpse) && god_likes_butchery(you.religion); bool removed_gloves = false; bool wpn_switch = false; - + if ( Options.easy_butcher && !can_butcher ) { // Try to find a butchering implement. @@ -355,10 +355,10 @@ bool butchery(int which_corpse) (you.weapon()->base_type == OBJ_WEAPONS) && item_cursed( *you.weapon() ); } - + // note that if barehanded then the user selected '-' when // switching weapons - + if (!barehand_butcher && (!wpn_switch || you.weapon() == NULL || !can_cut_meat(*you.weapon()))) @@ -373,17 +373,17 @@ bool butchery(int which_corpse) } else mpr("Maybe you should try using a sharper implement."); - + if ( !new_cursed && wpn_switch ) start_delay( DELAY_WEAPON_SWAP, 1, old_weapon ); - - return false; + + return false; } - + // switched to a good butchering knife can_butcher = true; } - + if ( can_butcher ) { const bool rotten = food_is_rotten(mitm[corpse_id]); @@ -398,12 +398,12 @@ bool butchery(int which_corpse) "sacrifice!" : " demands fresh blood!", you.religion); } - + // If we didn't switch weapons, we get in one turn of butchery; // otherwise the work has to happen in the delay. if (!wpn_switch && !removed_gloves) ++mitm[corpse_id].plus2; - + int work_req = 4 - mitm[corpse_id].plus2; if (work_req < 0) work_req = 0; @@ -427,7 +427,7 @@ bool butchery(int which_corpse) if ( removed_gloves ) start_delay( DELAY_ARMOUR_ON, 1, old_gloves ); - you.turn_is_over = true; + you.turn_is_over = true; return true; } @@ -644,13 +644,35 @@ static bool food_change(bool suppress_message) if (newstate < HS_SATIATED) interrupt_activity( AI_HUNGRY ); - else if (newstate == HS_ENGORGED && you.species == SP_VAMPIRE - && you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT - && you.duration[DUR_TRANSFORMATION] > 2) + + if (you.species == SP_VAMPIRE) { - mpr("Your bloodfilled body can't sustain your transformation much " - "longer.", MSGCH_WARN); - you.duration[DUR_TRANSFORMATION] = 2; + if (newstate <= HS_SATIATED) + { + if (you.duration[DUR_BERSERKER] > 1) + { + mpr("Your bloodless body can't sustain your rage any " + "longer.", MSGCH_DURATION); + you.duration[DUR_BERSERKER] = 1; + } + int transform = you.attribute[ATTR_TRANSFORMATION]; + if (transform != TRAN_NONE && transform != TRAN_BAT + && you.duration[DUR_TRANSFORMATION] > 2) + { + mpr("Your bloodless body can't sustain your " + "transformation much longer.", MSGCH_DURATION); + you.duration[DUR_TRANSFORMATION] = 2; + } + } + else if (newstate == HS_ENGORGED + && you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT + && you.duration[DUR_TRANSFORMATION] > 5) + { + mpr("Your bloodfilled body can't sustain your transformation much " + "longer.", MSGCH_WARN); + // give more time because suddenly stopping flying can be lethal + you.duration[DUR_TRANSFORMATION] = 5; + } } if (!suppress_message) @@ -740,7 +762,7 @@ void eat_from_inventory(int which_inventory_slot) { if (you.species != SP_VAMPIRE) return; - + const int mons_type = food.plus; const bool rotten = food_is_rotten(food); const int chunk_type @@ -816,10 +838,10 @@ void eat_floor_item(int item_link) const int intel = mons_intel( food.plus ) - I_ANIMAL; const bool cannibal = is_player_same_species( food.plus ); const bool rotten = food_is_rotten(food); - + if (!prompt_eat_chunk(food, rotten)) return; - + eat_chunk(determine_chunk_effect(chunk_type, rotten), cannibal, intel); } else @@ -881,7 +903,7 @@ static const char *chunk_flavour_phrase(bool likes_chunks) { const int gourmand = you.duration[DUR_GOURMAND]; if (gourmand >= GOURMAND_MAX) - phrase = + phrase = one_chance_in(1000)? "tastes like chicken!" : "tastes great."; else if (gourmand > GOURMAND_MAX * 75 / 100) @@ -917,23 +939,23 @@ static int apply_herbivore_chunk_effects(int nutrition) static int chunk_nutrition(bool likes_chunks) { int nutrition = CHUNK_BASE_NUTRITION; - + if (likes_chunks || you.hunger_state < HS_SATIATED) { return (likes_chunks? nutrition : apply_herbivore_chunk_effects(nutrition)); } - const int gourmand = + const int gourmand = wearing_amulet(AMU_THE_GOURMAND)? you.duration[DUR_GOURMAND] : 0; - int effective_nutrition = + int effective_nutrition = nutrition * (gourmand + GOURMAND_NUTRITION_BASE) / (GOURMAND_MAX + GOURMAND_NUTRITION_BASE); - + #ifdef DEBUG_DIAGNOSTICS const int epercent = effective_nutrition * 100 / nutrition; - mprf(MSGCH_DIAGNOSTICS, + mprf(MSGCH_DIAGNOSTICS, "Gourmand factor: %d, chunk base: %d, effective: %d, %%: %d", gourmand, nutrition, @@ -1038,7 +1060,7 @@ static void eat_chunk( int chunk_effect, bool cannibal, int mon_intel ) did_god_conduct( DID_CANNIBALISM, 10 ); else if (mon_intel > 0) did_god_conduct( DID_EAT_SOULED_BEING, mon_intel); - + if (do_eat) { start_delay( DELAY_EAT, 2, (suppress_msg) ? 0 : nutrition ); @@ -1256,7 +1278,7 @@ static void eating(unsigned char item_class, int item_type) temp_rand = random2(6) + 2; else temp_rand = random2(9); - + mprf("Mmm... %s", (temp_rand == 0) ? "Ham and pineapple." : (temp_rand == 2) ? "Vegetable." : @@ -1340,10 +1362,10 @@ bool can_ingest(int what_isit, int kindof_thing, bool suppress_msg, bool reqid, { return (true); } - + if (!suppress_msg) mpr("Blech - you need blood!"); - + return (false); } @@ -1353,7 +1375,7 @@ bool can_ingest(int what_isit, int kindof_thing, bool suppress_msg, bool reqid, // ur_chunkslover not defined in terms of ur_carnivorous because // a player could be one and not the other IMHO - 13mar2000 {dlb} - bool ur_chunkslover = ( + bool ur_chunkslover = ( (check_hunger? you.hunger_state <= HS_HUNGRY : true) || you.omnivorous() || you.mutation[MUT_CARNIVOROUS]); @@ -1367,7 +1389,7 @@ bool can_ingest(int what_isit, int kindof_thing, bool suppress_msg, bool reqid, mpr("Blech - you need blood!"); return false; } - + switch (kindof_thing) { case FOOD_BREAD_RATION: @@ -1450,7 +1472,7 @@ bool can_ingest(int what_isit, int kindof_thing, bool suppress_msg, bool reqid, case OBJ_POTIONS: // called by lua if (get_ident_type(OBJ_POTIONS, kindof_thing) != ID_KNOWN_TYPE) return true; - + switch (kindof_thing) { case POT_BLOOD: @@ -1645,7 +1667,7 @@ static bool vampire_consume_corpse(const int mons_type, const int max_chunks, int chunk_amount = 1 + random2(max_chunks); chunk_amount = stepdown_value( chunk_amount, 4, 4, 12, 12 ); int mass = CHUNK_BASE_NUTRITION * chunk_amount; - + int food_value = 0, hp_amt = 0, mp_amt = 0; if (rotten) @@ -1730,7 +1752,7 @@ static bool vampire_consume_corpse(const int mons_type, const int max_chunks, // The delay for eating a chunk (mass 1000) is 2 // Here the base nutrition value equals that of chunks, // but the delay should be greater. - start_delay( DELAY_EAT, mass / 400 ); + start_delay( DELAY_EAT, mass / 400 ); return true; } // end vampire_consume_corpse() diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc index 461f4341de..549fce4a71 100644 --- a/crawl-ref/source/item_use.cc +++ b/crawl-ref/source/item_use.cc @@ -3515,7 +3515,8 @@ void drink( int slot ) dec_inv_item_quantity( item_slot, 1 ); you.turn_is_over = true; - lessen_hunger(40, true); + if (you.species != SP_VAMPIRE) + lessen_hunger(40, true); } // end drink() bool _drink_fountain() diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 6d09c966e1..1ac798b66e 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -1097,8 +1097,9 @@ static undead_state_type _get_undead_state(const species_type sp) case SP_MUMMY: return US_UNDEAD; case SP_GHOUL: - case SP_VAMPIRE: return US_HUNGRY_DEAD; + case SP_VAMPIRE: + return US_SEMI_UNDEAD; default: ASSERT(!_species_is_undead(sp)); return (US_ALIVE); diff --git a/crawl-ref/source/spl-book.cc b/crawl-ref/source/spl-book.cc index bd12cfdad0..ff1482983a 100644 --- a/crawl-ref/source/spl-book.cc +++ b/crawl-ref/source/spl-book.cc @@ -1081,7 +1081,7 @@ bool undead_cannot_memorise(spell_type spell, char being) { switch (being) { - case US_HUNGRY_DEAD: + case US_HUNGRY_DEAD: // Ghouls switch (spell) { //case SPELL_REGENERATION: @@ -1106,7 +1106,22 @@ bool undead_cannot_memorise(spell_type spell, char being) } break; - case US_UNDEAD: + case US_SEMI_UNDEAD: // Vampires + switch (spell) + { + case SPELL_BORGNJORS_REVIVIFICATION: + case SPELL_DEATHS_DOOR: + case SPELL_NECROMUTATION: + case SPELL_ALTER_SELF: + return true; + default: + // also, the above US_HUNGRY_DEAD spells are not castable + // when satiated or worse + return false; + } + break; + + case US_UNDEAD: // Mummies switch (spell) { case SPELL_AIR_WALK: diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc index 24cb234962..de5204436c 100644 --- a/crawl-ref/source/spl-cast.cc +++ b/crawl-ref/source/spl-cast.cc @@ -69,7 +69,7 @@ */ #define WILD_MAGIC_NASTINESS 150 -static bool surge_identify_boosters(spell_type spell) +static bool _surge_identify_boosters(spell_type spell) { const unsigned int typeflags = get_spell_disciplines(spell); if ( (typeflags & SPTYP_FIRE) || (typeflags & SPTYP_ICE) ) @@ -111,7 +111,7 @@ static bool surge_identify_boosters(spell_type spell) ring.name(DESC_INVENTORY_EQUIP).c_str()); } } - + return true; } } @@ -119,11 +119,11 @@ static bool surge_identify_boosters(spell_type spell) return false; } -static void surge_power(spell_type spell) +static void _surge_power(spell_type spell) { int enhanced = 0; - surge_identify_boosters(spell); + _surge_identify_boosters(spell); //jmf: simplified enhanced += spell_enhancement(get_spell_disciplines(spell)); @@ -141,7 +141,7 @@ static void surge_power(spell_type spell) } } // end surge_power() -static std::string spell_base_description(spell_type spell) +static std::string _spell_base_description(spell_type spell) { std::ostringstream desc; @@ -160,9 +160,9 @@ static std::string spell_base_description(spell_type spell) desc << '/'; desc << spelltype_name(1 << i); already = true; - } + } } - + const int so_far = desc.str().length(); if ( so_far < 60 ) desc << std::string(60 - so_far, ' '); @@ -174,7 +174,7 @@ static std::string spell_base_description(spell_type spell) return desc.str(); } -static std::string spell_extra_description(spell_type spell) +static std::string _spell_extra_description(spell_type spell) { std::ostringstream desc; @@ -214,13 +214,13 @@ int list_spells() if (spell != SPELL_NO_SPELL) { ToggleableMenuEntry* me = - new ToggleableMenuEntry(spell_base_description(spell), - spell_extra_description(spell), + new ToggleableMenuEntry(_spell_base_description(spell), + _spell_extra_description(spell), MEL_ITEM, 1, letter); spell_menu.add_entry(me); } } - + std::vector sel = spell_menu.show(); redraw_screen(); if ( sel.empty() ) @@ -235,13 +235,13 @@ int list_spells() } } -static int apply_spellcasting_success_boosts(spell_type spell, int chance) +static int _apply_spellcasting_success_boosts(spell_type spell, int chance) { int wizardry = player_mag_abil(false); int fail_reduce = 100; int wiz_factor = 87; - if (you.religion == GOD_VEHUMET + if (you.religion == GOD_VEHUMET && you.duration[DUR_PRAYER] && (!player_under_penance() && you.piety >= 50) && (spell_typematch(spell, SPTYP_CONJURATION) @@ -299,7 +299,7 @@ int spell_fail(spell_type spell) // Truth is, even a much worse penalty than the above can // easily be overcome by gaining spell skills... and a lot // faster than any reasonable rate of bonus here. - int lim_str = (you.strength > 30) ? 30 : + int lim_str = (you.strength > 30) ? 30 : (you.strength < 10) ? 10 : you.strength; armour -= ((you.skills[SK_ARMOUR] * lim_str) / 15); @@ -336,7 +336,7 @@ int spell_fail(spell_type spell) chance += armour; } - if (you.equip[EQ_WEAPON] != -1 + if (you.equip[EQ_WEAPON] != -1 && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_WEAPONS) { int wpn_penalty = (3 * (property( you.inv[you.equip[EQ_WEAPON]], PWPN_SPEED ) - 12)) / 2; @@ -452,13 +452,9 @@ int spell_fail(spell_type spell) break; } } - - // vampires can cast while starving, but with increased difficulty - if (you.species == SP_VAMPIRE && you.hunger_state == HS_STARVING) - chance2 += 20; // Apply the effects of Vehumet prayer and items of wizardry. - chance2 = apply_spellcasting_success_boosts(spell, chance2); + chance2 = _apply_spellcasting_success_boosts(spell, chance2); if (chance2 > 100) chance2 = 100; @@ -474,8 +470,8 @@ int calc_spell_power(spell_type spell, bool apply_intel, bool fail_rate_check) // When checking failure rates, wizardry is handled after the various // stepping calulations. - int power = - (you.skills[SK_SPELLCASTING] / 2) + int power = + (you.skills[SK_SPELLCASTING] / 2) + (fail_rate_check? 0 : player_mag_abil(false)); int enhanced = 0; @@ -502,7 +498,7 @@ int calc_spell_power(spell_type spell, bool apply_intel, bool fail_rate_check) if (apply_intel) power = (power * you.intel) / 10; - // [dshaligram] Enhancers don't affect fail rates any more, only spell + // [dshaligram] Enhancers don't affect fail rates any more, only spell // power. Note that this does not affect Vehumet's boost in castability. if (!fail_rate_check) enhanced = spell_enhancement( disciplines ); @@ -690,7 +686,7 @@ bool cast_a_spell() exercise_spell( spell, true, cast_result == SPRET_SUCCESS ); did_god_conduct( DID_SPELL_CASTING, 1 + random2(5) ); } - + dec_mp( spell_mana(spell) ); if (!staff_energy && you.is_undead != US_UNDEAD) @@ -706,11 +702,11 @@ bool cast_a_spell() return (true); } // end cast_a_spell() -// "Utility" spells for the sake of simplicity are currently ones with -// enchantments, translocations, or divinations. +// "Utility" spells for the sake of simplicity are currently ones with +// enchantments, translocations, or divinations. bool spell_is_utility_spell( spell_type spell_id ) { - return (spell_typematch( spell_id, + return (spell_typematch( spell_id, SPTYP_ENCHANTMENT | SPTYP_TRANSLOCATION | SPTYP_DIVINATION )); } @@ -823,7 +819,34 @@ void spellcasting_side_effects(spell_type spell, bool idonly = false) alert_nearby_monsters(); } -static bool spell_is_uncastable(spell_type spell) +static bool _vampire_cannot_cast(spell_type spell) +{ + if (you.species != SP_VAMPIRE) + return false; + + if (you.hunger_state >= HS_FULL) + return false; + + // Satiated or less + switch (spell) + { + case SPELL_RESIST_POISON: + case SPELL_CURE_POISON_II: + case SPELL_TAME_BEASTS: + case SPELL_BLADE_HANDS: + case SPELL_SPIDER_FORM: + case SPELL_ICE_FORM: + case SPELL_STATUE_FORM: + case SPELL_DRAGON_FORM: + case SPELL_AIR_WALK: + case SPELL_BERSERKER_RAGE: + return true; + default: + return false; + } +} + +static bool _spell_is_uncastable(spell_type spell) { if (you.is_undead && spell_typematch(spell, SPTYP_HOLY)) { @@ -847,6 +870,12 @@ static bool spell_is_uncastable(spell_type spell) return (true); } + if (_vampire_cannot_cast( spell )) + { + mpr("Your current blood level is not sufficient to cast that spell."); + return (true); + } + return (false); } @@ -861,7 +890,7 @@ spret_type your_spells( spell_type spell, int powc, bool allow_fail ) // [dshaligram] Any action that depends on the spellcasting attempt to have // succeeded must be performed after the switch() - if (spell_is_uncastable(spell)) + if (_spell_is_uncastable(spell)) return (SPRET_ABORT); const int flags = get_spell_flags(spell); @@ -870,7 +899,7 @@ spret_type your_spells( spell_type spell, int powc, bool allow_fail ) // XXX: This handles only some of the cases where spells need targeting... // there are others that do their own that will be missed by this - // (and thus will not properly ESC without cost because of it). + // (and thus will not properly ESC without cost because of it). // Hopefully, those will eventually be fixed. -- bwr if (flags & SPFLAG_TARGETING_MASK) { @@ -878,8 +907,8 @@ spret_type your_spells( spell_type spell, int powc, bool allow_fail ) (testbits(flags, SPFLAG_HELPFUL) ? TARG_FRIEND : TARG_ENEMY); targeting_type dir = - (testbits( flags, SPFLAG_TARGET ) ? DIR_TARGET : - testbits( flags, SPFLAG_GRID ) ? DIR_TARGET : + (testbits( flags, SPFLAG_TARGET ) ? DIR_TARGET : + testbits( flags, SPFLAG_GRID ) ? DIR_TARGET : testbits( flags, SPFLAG_DIR ) ? DIR_DIR : DIR_NONE); const char *prompt = get_spell_target_prompt(spell); @@ -920,7 +949,7 @@ spret_type your_spells( spell_type spell, int powc, bool allow_fail ) const bool needs_path = !(testbits(flags, SPFLAG_GRID) || testbits(flags, SPFLAG_TARGET)); - + if ( !spell_direction( spd, beam, dir, targ, needs_path, prompt ) ) return (SPRET_ABORT); @@ -931,19 +960,19 @@ spret_type your_spells( spell_type spell, int powc, bool allow_fail ) { mpr( "Sorry, this spell works on others only." ); } - else + else { canned_msg(MSG_UNTHINKING_ACT); } return (SPRET_ABORT); - } + } } // enhancers only matter for calc_spell_power() and spell_fail() // not sure about this: is it flavour or misleading? if (powc == 0 || allow_fail) - surge_power(spell); + _surge_power(spell); // Added this so that the passed in powc can have meaning -- bwr if (powc == 0) @@ -1063,14 +1092,14 @@ spret_type your_spells( spell_type spell, int powc, bool allow_fail ) crawl_state.cant_cmd_repeat("You can't repeat delayed fireball."); // This spell has two main advantages over Fireball: // - // (1) The release is instantaneous, so monsters will not + // (1) The release is instantaneous, so monsters will not // get an action before the player... this allows the // player to hit monsters with a double fireball (this // is why we only allow one delayed fireball at a time, - // if you want to allow for more, then the release should + // if you want to allow for more, then the release should // take at least some amount of time). // - // The casting of this spell still costs a turn. So + // The casting of this spell still costs a turn. So // casting Delayed Fireball and immediately releasing // the fireball is only slightly different than casting // a regular Fireball (monsters act in the middle instead @@ -1080,9 +1109,9 @@ spret_type your_spells( spell_type spell, int powc, bool allow_fail ) // both). // // (2) When the fireball is released, it is guaranteed to - // go off... the spell only fails at this point. This can - // be a large advantage for characters who have difficulty - // casting Fireball in their standard equipment. However, + // go off... the spell only fails at this point. This can + // be a large advantage for characters who have difficulty + // casting Fireball in their standard equipment. However, // the power level for the actual fireball is determined at // release, so if you do swap out your enhancers you'll // get a less powerful ball when its released. -- bwr @@ -1960,7 +1989,7 @@ void exercise_spell( spell_type spell, bool spc, bool success ) const int exercise_amount = exercise( skill, workout ); exer += exercise_amount; - exer_norm += + exer_norm += exercise_amount * species_skills(skill, you.species) / ref_skill; } @@ -1978,11 +2007,11 @@ void exercise_spell( spell_type spell, bool spc, bool success ) if (spc) { - const int exercise_amount = - exercise(SK_SPELLCASTING, one_chance_in(3) ? 1 + const int exercise_amount = + exercise(SK_SPELLCASTING, one_chance_in(3) ? 1 : random2(1 + random2(diff))); exer += exercise_amount; - exer_norm += exercise_amount * + exer_norm += exercise_amount * species_skills(SK_SPELLCASTING, you.species) / ref_skill; } @@ -1990,7 +2019,7 @@ void exercise_spell( spell_type spell, bool spc, bool success ) did_god_conduct( DID_SPELL_PRACTISE, exer_norm ); } // end exercise_spell() -static bool send_abyss(const char *cause) +static bool _send_abyss(const char *cause) { if (you.level_type != LEVEL_ABYSS) { @@ -2004,7 +2033,7 @@ static bool send_abyss(const char *cause) } } -static void miscast_conjuration(int severity, const char* cause) +static void _miscast_conjuration(int severity, const char* cause) { bolt beam; switch (severity) @@ -2079,7 +2108,7 @@ static void miscast_conjuration(int severity, const char* cause) beam.damage = dice_def( 3, 12 ); beam.flavour = BEAM_MISSILE; // unsure about this // BEAM_EXPLOSION instead? {dlb} - + beam.target_x = you.x_pos; beam.target_y = you.y_pos; beam.name = "explosion"; @@ -2091,7 +2120,7 @@ static void miscast_conjuration(int severity, const char* cause) beam.aux_source = cause; beam.ex_size = 1; beam.is_explosion = true; - + explosion(beam); break; } @@ -2121,14 +2150,14 @@ static void miscast_conjuration(int severity, const char* cause) beam.aux_source = cause; beam.ex_size = coinflip()?1:2; beam.is_explosion = true; - + explosion(beam); break; } } } -static void miscast_enchantment(int severity, const char* cause) +static void _miscast_enchantment(int severity, const char* cause) { switch (severity) { @@ -2233,7 +2262,7 @@ static void miscast_enchantment(int severity, const char* cause) } } -static void miscast_translocation(int severity, const char* cause) +static void _miscast_translocation(int severity, const char* cause) { switch (severity) { @@ -2330,7 +2359,7 @@ static void miscast_translocation(int severity, const char* cause) } break; case 6: - send_abyss(cause); + _send_abyss(cause); break; } break; @@ -2351,7 +2380,7 @@ static void miscast_translocation(int severity, const char* cause) potion_effect(POT_CONFUSION, 60); break; case 2: - send_abyss(cause); + _send_abyss(cause); break; case 3: mpr("You feel saturated with unharnessed energies!"); @@ -2362,7 +2391,7 @@ static void miscast_translocation(int severity, const char* cause) } } -static void miscast_summoning(int severity, const char* cause) +static void _miscast_summoning(int severity, const char* cause) { switch (severity) { @@ -2529,14 +2558,14 @@ static void miscast_summoning(int severity, const char* cause) break; case 3: - send_abyss(cause); + _send_abyss(cause); break; } break; - } + } } -static void miscast_divination(int severity, const char* cause) +static void _miscast_divination(int severity, const char* cause) { switch (severity) { @@ -2600,7 +2629,9 @@ static void miscast_divination(int severity, const char* cause) mpr("You suddenly recall your previous life!"); else if (lose_stat(STAT_INTELLIGENCE, 1 + random2(3), false, cause)) + { mpr("You have damaged your brain!"); + } else mpr("You have a terrible headache."); break; @@ -2629,7 +2660,9 @@ static void miscast_divination(int severity, const char* cause) mpr("You suddenly recall your previous life."); else if (lose_stat(STAT_INTELLIGENCE, 3 + random2(3), false, cause)) + { mpr("You have damaged your brain!"); + } else mpr("You have a terrible headache."); break; @@ -2640,7 +2673,7 @@ static void miscast_divination(int severity, const char* cause) } } -static void miscast_necromancy(int severity, const char* cause) +static void _miscast_necromancy(int severity, const char* cause) { if (you.religion == GOD_KIKUBAAQUDGHA && (!player_under_penance() && you.piety >= piety_breakpoint(1) @@ -2815,7 +2848,7 @@ static void miscast_necromancy(int severity, const char* cause) } } -static void miscast_transmigration(int severity, const char* cause) +static void _miscast_transmigration(int severity, const char* cause) { switch (severity) { @@ -2912,7 +2945,7 @@ static void miscast_transmigration(int severity, const char* cause) { const bool failMsg = !give_bad_mutation(); if (coinflip()) - give_bad_mutation(false, failMsg); + give_bad_mutation(false, failMsg); ouch(5 + random2avg(23, 2), 0, KILLED_BY_WILD_MAGIC, cause); } break; @@ -2921,7 +2954,7 @@ static void miscast_transmigration(int severity, const char* cause) } } -static void miscast_fire(int severity, const char* cause) +static void _miscast_fire(int severity, const char* cause) { bolt beam; switch (severity) @@ -3061,7 +3094,7 @@ static void miscast_fire(int severity, const char* cause) } } -static void miscast_ice(int severity, const char* cause) +static void _miscast_ice(int severity, const char* cause) { bolt beam; switch (severity) @@ -3151,7 +3184,7 @@ static void miscast_ice(int severity, const char* cause) beam.aux_source = cause; beam.ex_size = 1; beam.is_explosion = true; - + explosion(beam); break; } @@ -3179,7 +3212,7 @@ static void miscast_ice(int severity, const char* cause) } } -static void miscast_earth(int severity, const char* cause) +static void _miscast_earth(int severity, const char* cause) { bolt beam; switch (severity) @@ -3262,12 +3295,12 @@ static void miscast_earth(int severity, const char* cause) beam.target_y = you.y_pos; beam.name = "explosion"; beam.colour = CYAN; - + if (one_chance_in(5)) beam.colour = BROWN; if (one_chance_in(5)) beam.colour = LIGHTCYAN; - + beam.beam_source = NON_MONSTER; beam.thrower = (cause) ? KILL_MISC : KILL_YOU; beam.aux_source.clear(); @@ -3275,7 +3308,7 @@ static void miscast_earth(int severity, const char* cause) beam.aux_source = cause; beam.ex_size = 1; beam.is_explosion = true; - + explosion(beam); break; } @@ -3283,7 +3316,7 @@ static void miscast_earth(int severity, const char* cause) } } -static void miscast_air(int severity, const char* cause) +static void _miscast_air(int severity, const char* cause) { bolt beam; switch (severity) @@ -3381,7 +3414,7 @@ static void miscast_air(int severity, const char* cause) beam.aux_source = cause; beam.ex_size = one_chance_in(4)?1:2; beam.is_explosion = true; - + explosion(beam); break; case 1: @@ -3394,7 +3427,7 @@ static void miscast_air(int severity, const char* cause) } } -static void miscast_poison(int severity, const char* cause) +static void _miscast_poison(int severity, const char* cause) { switch (severity) { @@ -3508,7 +3541,7 @@ static void miscast_poison(int severity, const char* cause) break; case 2: if (player_res_poison()) - canned_msg(MSG_NOTHING_HAPPENS); + canned_msg(MSG_NOTHING_HAPPENS); else lose_stat(STAT_RANDOM, 1 + random2avg(5, 2), false, cause); break; @@ -3523,7 +3556,7 @@ static void miscast_poison(int severity, const char* cause) * force_effect forces a certain severity of effect to occur * (set to 100 to avoid forcing.) */ -void miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail, +void miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail, int force_effect, const char *cause ) { if (sp_type == SPTYP_RANDOM) @@ -3554,7 +3587,7 @@ void miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail, sever = 0; #if DEBUG_DIAGNOSTICS - mprf(MSGCH_DIAGNOSTICS, "Sptype: %u, failure1: %d, failure2: %d", + mprf(MSGCH_DIAGNOSTICS, "Sptype: %u, failure1: %d, failure2: %d", sp_type, old_fail, sever ); #endif @@ -3563,18 +3596,18 @@ void miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail, switch (sp_type) { - case SPTYP_CONJURATION: miscast_conjuration(sever, cause); break; - case SPTYP_ENCHANTMENT: miscast_enchantment(sever, cause); break; - case SPTYP_TRANSLOCATION: miscast_translocation(sever, cause); break; - case SPTYP_SUMMONING: miscast_summoning(sever, cause); break; - case SPTYP_DIVINATION: miscast_divination(sever, cause); break; - case SPTYP_NECROMANCY: miscast_necromancy(sever, cause); break; - case SPTYP_TRANSMIGRATION: miscast_transmigration(sever, cause); break; - case SPTYP_FIRE: miscast_fire(sever, cause); break; - case SPTYP_ICE: miscast_ice(sever, cause); break; - case SPTYP_EARTH: miscast_earth(sever, cause); break; - case SPTYP_AIR: miscast_air(sever, cause); break; - case SPTYP_POISON: miscast_poison(sever, cause); break; + case SPTYP_CONJURATION: _miscast_conjuration(sever, cause); break; + case SPTYP_ENCHANTMENT: _miscast_enchantment(sever, cause); break; + case SPTYP_TRANSLOCATION: _miscast_translocation(sever, cause); break; + case SPTYP_SUMMONING: _miscast_summoning(sever, cause); break; + case SPTYP_DIVINATION: _miscast_divination(sever, cause); break; + case SPTYP_NECROMANCY: _miscast_necromancy(sever, cause); break; + case SPTYP_TRANSMIGRATION: _miscast_transmigration(sever, cause); break; + case SPTYP_FIRE: _miscast_fire(sever, cause); break; + case SPTYP_ICE: _miscast_ice(sever, cause); break; + case SPTYP_EARTH: _miscast_earth(sever, cause); break; + case SPTYP_AIR: _miscast_air(sever, cause); break; + case SPTYP_POISON: _miscast_poison(sever, cause); break; } xom_is_stimulated(sever); @@ -3631,18 +3664,18 @@ int spell_power_colour(spell_type spell) return GREEN; } -static int power_to_barcount( int power ) +static int _power_to_barcount( int power ) { if ( power == -1 ) return -1; - + const int breakpoints[] = { 5, 10, 15, 25, 35, 50, 75, 100, 150 }; int result = 0; for ( unsigned int i = 0; i < ARRAYSIZE(breakpoints); ++i ) if ( power > breakpoints[i] ) ++result; - return result + 1; + return result + 1; } int spell_power_bars( spell_type spell ) @@ -3651,13 +3684,13 @@ int spell_power_bars( spell_type spell ) if ( cap == 0 ) return -1; const int power = std::min(calc_spell_power(spell, true), cap); - return power_to_barcount(power); + return _power_to_barcount(power); } std::string spell_power_string(spell_type spell) { const int numbars = spell_power_bars(spell); - const int capbars = power_to_barcount(spell_power_cap(spell)); + const int capbars = _power_to_barcount(spell_power_cap(spell)); ASSERT( numbars <= capbars ); if ( numbars < 0 ) return "N/A"; diff --git a/crawl-ref/source/transfor.cc b/crawl-ref/source/transfor.cc index 3e28135e9d..d825d88c6f 100644 --- a/crawl-ref/source/transfor.cc +++ b/crawl-ref/source/transfor.cc @@ -155,7 +155,9 @@ bool transform(int pow, transformation_type which_trans) if (you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE) untransform(); - if (you.is_undead && (you.species != SP_VAMPIRE || which_trans != TRAN_BAT)) + if (you.is_undead + && (you.species != SP_VAMPIRE + || which_trans != TRAN_BAT && you.hunger_state <= HS_SATIATED)) { mpr("Your unliving flesh cannot be transformed in this way."); return (false); @@ -187,7 +189,7 @@ bool transform(int pow, transformation_type which_trans) { rem_stuff.erase(EQ_HELMET); } - + if (check_for_cursed_equipment( rem_stuff )) return (false); @@ -214,11 +216,11 @@ bool transform(int pow, transformation_type which_trans) { rem_stuff.erase(EQ_HELMET); } - + // high ev, low ac, high speed if (check_for_cursed_equipment( rem_stuff )) return false; - + mprf("You turn into a %sbat.", you.species == SP_VAMPIRE ? "vampire " : ""); @@ -234,12 +236,12 @@ bool transform(int pow, transformation_type which_trans) "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); return (true); - - case TRAN_ICE_BEAST: // also AC +3, cold +3, fire -1, pois +1 + + case TRAN_ICE_BEAST: // also AC +3, cold +3, fire -1, pois +1 rem_stuff.erase(EQ_CLOAK); // ice beasts CAN wear soft helmets if ( you.equip[EQ_HELMET] == -1 @@ -250,7 +252,7 @@ bool transform(int pow, transformation_type which_trans) if (check_for_cursed_equipment( rem_stuff )) return false; - + mpr( "You turn into a creature of crystalline ice." ); remove_equipment( rem_stuff ); @@ -350,7 +352,7 @@ bool transform(int pow, transformation_type which_trans) you.symbol = 'D'; you.colour = GREEN; - + if (you.attribute[ATTR_HELD]) { mpr("The net rips apart!"); @@ -404,7 +406,7 @@ bool transform(int pow, transformation_type which_trans) rem_stuff.insert(EQ_LEFT_RING); rem_stuff.insert(EQ_RIGHT_RING); rem_stuff.insert(EQ_AMULET); - + if (check_for_cursed_equipment( rem_stuff )) return false; @@ -426,7 +428,7 @@ bool transform(int pow, transformation_type which_trans) "gaining the air transformation" ); you.symbol = '#'; you.colour = DARKGREY; - + if (you.attribute[ATTR_HELD]) { mpr("You drift through the net!"); @@ -485,12 +487,12 @@ void untransform(void) // must be unset first or else infinite loops might result -- bwr const transformation_type old_form = static_cast(you.attribute[ ATTR_TRANSFORMATION ]); - + you.attribute[ ATTR_TRANSFORMATION ] = TRAN_NONE; you.duration[ DUR_TRANSFORMATION ] = 0; int hp_downscale = 10; - + switch (old_form) { case TRAN_SPIDER: @@ -519,7 +521,7 @@ void untransform(void) modify_stat( STAT_STRENGTH, -2, true, "losing the statue transformation"); - // Note: if the core goes down, the combined effect soon disappears, + // 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; @@ -528,19 +530,19 @@ void untransform(void) you.duration[DUR_STONESKIN] = 1; hp_downscale = 15; - + break; case TRAN_ICE_BEAST: mpr( "You warm up again.", MSGCH_DURATION ); - // Note: if the core goes down, the combined effect soon disappears, + // 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; hp_downscale = 12; - + break; case TRAN_DRAGON: @@ -552,7 +554,7 @@ void untransform(void) move_player_to_grid( you.x_pos, you.y_pos, false, true, true ); hp_downscale = 16; - + break; case TRAN_LICH: @@ -581,7 +583,7 @@ void untransform(void) if (transform_can_butcher_barehanded(old_form)) stop_butcher_delay(); - + // 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 @@ -603,7 +605,7 @@ void untransform(void) else if (you.hp > you.hp_max) you.hp = you.hp_max; } - calc_hp(); + calc_hp(); } // end untransform() // XXX: This whole system is a mess as it still relies on special @@ -651,8 +653,8 @@ bool can_equip( equipment_type use_which, bool ignore_temporary ) && use_which != EQ_SHIELD); case TRAN_STATUE: - return (use_which == EQ_WEAPON - || use_which == EQ_CLOAK + return (use_which == EQ_WEAPON + || use_which == EQ_CLOAK || use_which == EQ_HELMET); case TRAN_ICE_BEAST: @@ -666,7 +668,7 @@ bool can_equip( equipment_type use_which, bool ignore_temporary ) return (true); } // end can_equip() -// raw comparison of an item, must use check_armour_shape for full version +// raw comparison of an item, must use check_armour_shape for full version bool transform_can_equip_type( int eq_slot ) { // FIXME FIXME FIXME @@ -708,14 +710,14 @@ void drop_everything(void) } // end drop_everything() // Used to mark transformations which override species/mutation intrinsics. -// If phys_scales is true then we're checking to see if the form keeps -// the physical (AC/EV) properties from scales... the special intrinsic +// If phys_scales is true then we're checking to see if the form keeps +// the physical (AC/EV) properties from scales... the special intrinsic // features (resistances, etc) are lost in those forms however. bool transform_changed_physiology( bool phys_scales ) { return (you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE && you.attribute[ATTR_TRANSFORMATION] != TRAN_BLADE_HANDS - && (!phys_scales + && (!phys_scales || (you.attribute[ATTR_TRANSFORMATION] != TRAN_LICH && you.attribute[ATTR_TRANSFORMATION] != TRAN_STATUE))); } -- cgit v1.2.3-54-g00ecf