plus: thrown weapon permabrand being removed when
DUR_WEAPON_BRAND is active
plus: double messaging of "You are now empty-handed."
Fix 2810517: Added a pre-ability requirements check that handles Lugonu's enter/exit abyss, berserking, recite, breath attacks and some more. If the requirements aren't met, the check fails before the success check, thus no turn is wasted.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@10360 c06c8d41-db1a-0410-9941-cceddc491573
QEM5F3M5TVOHKIPY75SUYD2EIGTTTMAC7PXIOKREQQMA7YLHQIGQC 2GW6RXMG75B5B5JL7FWZ22RJSGQ42FV4F2DBNQE3ZY4SWHN6O4BQC Z4GIMEXHU6YMHSULVXDODCADGM6S2QOG6N7D6J6W36HYXZHPXV2AC 7IPYQAVJ4QTC4X7P2DD5UXREZHQUFHXM2M5IYQEM5RQBXC4QCTIQC RJXHFK2ELCI2EP4W5WKPWUQFK7R72ZIK7AYFKXNZVX5DZZWSMYJAC D4RMJU7NPV6VPRNOO4ZU7EUCPAOYVEOWOG4VLBDHN5VUIOKG74WQC SU7SVV5BF353FB7Q5ANDJ3R3HYGNMBVS6H6D7GIWJZ6Y2YTJ7OOAC PFIHKKSI2SU7ZNCHISUMGOOXEONFY5PHAQARVGAG5VYI2NL5QDRQC DKISJVKAJJK2SVZSXGJ37K5SOVTDARVX6RPK3MAKVNGC36Z4YAZQC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC SSI2HXYXWAFH5ROTQ5JTTH62LQILJECBHGEK2TSIIQJBH7CSQWCAC ASLW3Z5PAVZSWJEMMMVZT226P44EKSAD47QS72JIFJESAI3RPN3AC YJ4Q65CCPG2R3O2CFICU6WS27ISYEHQGWIHNOOYPN2TIPKNXVX7QC KHHAE5ZK7ITEZVMMUKYROKECLE2RU5ZU5OQ4Z4XSRQXE2R65O67AC ODSARKFWKP2ZXJYUHXMLHGJUOX3OBRO25IHNCHWNRCGLTPWKH3QQC 3EUPIYJNWOMOQBP2Z5SGSMWK453BXJD6KL2WFTR3NM565MEBYASAC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC KXHG3CHEUCZX6UZXAQG6QXPS6IRTIJWGGZWYVAMHWYYTCM4KBUSQC VIHJ3Z75JN7BXWNOPWV3CWQZEA7K5DK36EKHCYMZC7SOSJYH2XHQC 7KWDC7XFNMBLSUO2HISIROBINZBX5T67LJEEXTAORXW2YZ7VWFGAC UZ6N6HOUPGVSPC5NQROEEDWMEGJA5XUWUY2AKH5QG65AZ25PVXDAC UEI5JAVCMN7Y2SACTEZPZSNFJWOJTC55G24Q6LKQCT4XNDH5ZQIAC WXSNNK2RXP3DQFAEQGQUZJHFWXJC7ZKG2WURZGL566UDM4YXFSWQC FXVDNB6MAAOSEP37HP7CIPPXNS7FDECN3GCRMT5UFFCKLHIL6IVAC PQ3SLWFD5CF33ZHBG2V7YJEKAL6HTSDYOV25OKUTBCW2QF7TL4AAC KBNY5FWKTEAKABFCLPC3QFKFSVZKAGXINPCIFV6WDSWFO4VCKNTAC JM7UAK777RAVDAVLQLEOBRTGNW2B47S5G55XITJXO243IUNZHVYQC BINKDWGFGUPTOA7IE5KK4ZIELGU5WC3X47MYXOWU4X43EGAC5DUAC 6ECDSRJ6V3FSIAQC6FZK5SV4NGXXR6PW5S4KADSPISPP36CXLTYQC ARORC5GJNHLAPL2MJ3PUYIAR55ETDDAPXYSYH4OBMXHADNWSGYPAC XX62GOJVDP352L4BH7MELNYXHMZNA6VAGF7B6RWWOSULX7VJR5YAC FLAGBNUNSIQNFDN53CDWABJRTTFWDL4PG34AI474ZKPXDEPYHOAQC RKBFYX6A3ORSXOVFPBGZFHL25AMX754YAT6M23FNGYXBXZ4DSFAAC 3ZWALZFSTSIVYXY4BAY6ANGINTDACZC6RSSJTEMQSTSUIE66YOBQC GZMPIDNMBXZ4B2ZWKREHBPAVN53J6WRVY5W5KY52KEBHKU6IW4IQC 3WAR2UAC4C4D2GOK4AUV4JITGFSBO3NIBAXGQZXSMFUTNTCLTU4AC PDOFPXD2X6VI23AHKCGQ5RVDBG74CNP2E3YOHKXLOARHHBXEK3HQC LFPHI3TJK5V4HPJJHCG5XATY23P25OVIZ4ITQVG354DJHPEPKU4AC DAVTHXRQBYQKWHKUKJVJ5EJXIFGVWMEHINLM3JE4FMV6AAYIBOVAC PRQVFUGUGPKI2Q74ODEI3CYUJQB63CKC6ONQTE3BTOHKXG4JCNLQC I2B33Z7NZGC33AMDSSK446AZZYWKPHWLAGULVHKKZU4MVB4BNJOAC 23PFLB2E4QHL5SF3Q2YV5FXRH6MFHENEU2ACVC572ZCYDXCBZVQAC G4TVXOLIF5X2MWV7I4UPT3MSQHRMGME6QRIIFAQ64C45JGYK7SIAC WFJK2QEDZ4FOXY75KP2JZMRZ27CTP6YATF64OV5UFT7QG3MFDRBAC LOJYD6QZRNLNDDZJKVBMKQIBPTKSRN2ETCYGNVV47M7L3QLUJUJAC 5LIWCQ5G74WIMISKX3SBMZFPVVYEDNUIREAK55XYR5RTNSHVGDYQC WHY6LRRJ5T2NSBE3IUCR4X3TOAH7TTK5NPUPUIFT7TPNJ6J4HBDAC 2VUJ2IMYI7MYLFMSPYAH6IEXIMFG4JUSUYLVCW7SZELHSLPIEL3AC OAQEGSRMAOE4UHILW4LSDKERKTPOJPGPJQ3R2FB5QFWFB764UGHQC if (you.duration[DUR_WEAPON_BRAND] && projected == LRET_THROWN)set_item_ego_type( item, OBJ_WEAPONS, SPWPN_NORMAL );
if (you.duration[DUR_WEAPON_BRAND] && projected != LRET_LAUNCHED&& throw_2 == you.equip[EQ_WEAPON]){set_item_ego_type(item, OBJ_WEAPONS, SPWPN_NORMAL);}
// Check prerequisites for a number of abilities.// Abort any attempt if these cannot be met, without losing the turn.// TODO: Many more cases need to be added!static bool _check_ability_possible(const ability_def& abil,bool hungerCheck = true){// Don't insta-starve the player.// (Happens at 100, losing consciousness possible from 500 downward.)if (hungerCheck && you.species != SP_VAMPIRE){const int expected_hunger = you.hunger - abil.food_cost * 2;#ifdef DEBUG_DIAGNOSTICSmprf(MSGCH_DIAGNOSTICS,"hunger: %d, max. food_cost: %d, expected hunger: %d",you.hunger, abil.food_cost * 2, expected_hunger);#endif// Safety margin for natural hunger, mutations etc.if (expected_hunger <= 150){mpr("You're too hungry.");return (false);}}switch (abil.ability){case ABIL_ZIN_RECITE:{const int result = check_recital_audience();if (result < 0){mpr("There's no appreciative audience!");return (false);}else if (result < 1){mpr("There's no-one here to preach to!");return (false);}return (true);}case ABIL_ZIN_CURE_ALL_MUTATIONS:return (how_mutated());case ABIL_ZIN_SANCTUARY:if (env.sanctuary_time){mpr("There's already a sanctuary in place on this level.");return (false);}return (true);case ABIL_ELYVILON_PURIFICATION:if (!you.disease && !you.rotting && !you.duration[DUR_POISONING]&& !you.duration[DUR_CONF] && !you.duration[DUR_SLOW]&& !you.duration[DUR_PARALYSIS] && !you.duration[DUR_PETRIFIED]){mpr("Nothing ails you!");return (false);}return (true);case ABIL_ELYVILON_RESTORATION:case ABIL_MUMMY_RESTORATION:if (you.strength == you.max_strength&& you.intel == you.max_intel&& you.dex == you.max_dex&& (abil.ability == ABIL_MUMMY_RESTORATION || !player_rotted())){mprf("You don't need to restore your stats%s!",abil.ability == ABIL_ELYVILON_RESTORATION ? " or hit points": "");return (false);}return (true);case ABIL_LUGONU_ABYSS_EXIT:if (you.level_type != LEVEL_ABYSS){mpr("You aren't in the Abyss!");return (false);}return (true);case ABIL_LUGONU_CORRUPT:return (!is_level_incorruptible());case ABIL_LUGONU_ABYSS_ENTER:if (you.level_type == LEVEL_ABYSS){mpr("You're already here!");return (false);}else if (you.level_type == LEVEL_PANDEMONIUM){mpr("That doesn't work from Pandemonium.");return (false);}return (true);case ABIL_SIF_MUNA_FORGET_SPELL:if (you.spell_no == 0){mpr("You don't know any spells.");return (false);}return (true);
case ABIL_SPIT_POISON:case ABIL_BREATHE_FIRE:case ABIL_BREATHE_FROST:case ABIL_BREATHE_POISON:case ABIL_BREATHE_LIGHTNING:case ABIL_BREATHE_POWER:case ABIL_BREATHE_STICKY_FLAME:case ABIL_BREATHE_STEAM:if (you.duration[DUR_BREATH_WEAPON]){canned_msg(MSG_CANNOT_DO_YET);return (false);}return (true);case ABIL_EVOKE_BERSERK:case ABIL_TROG_BERSERK:if (you.hunger_state < HS_SATIATED){mpr("You're too hungry to berserk.");return (false);}return (you.can_go_berserk(true) && berserk_check_wielded_weapon());case ABIL_MAPPING:if (player_mutation_level(MUT_MAPPING) < 3&& (you.level_type == LEVEL_PANDEMONIUM|| !player_in_mappable_area())){mpr("You feel momentarily disoriented.");return (false);}return (true);case ABIL_FLY_II:if (you.duration[DUR_EXHAUSTED]){mpr("You're too exhausted to fly.");return (false);}else if (you.burden_state != BS_UNENCUMBERED){mpr("You're carrying too much weight to fly.");return (false);}return (true);case ABIL_TORMENT:if (you.is_undead){mpr("The unliving cannot use this ability.");return (false);}return (true);case ABIL_EVOKE_TURN_INVISIBLE: // ring, randarts, darkness itemsif (you.hunger_state < HS_SATIATED){mpr("You're too hungry to turn invisible.");return (false);}return (true);default:return (true);}}
// Don't insta-starve the player.// (Happens at 100, losing consciousness possible from 500 downward.)if (hungerCheck && you.species != SP_VAMPIRE){const int expected_hunger = you.hunger - abil.food_cost * 2;#ifdef DEBUG_DIAGNOSTICSmprf(MSGCH_DIAGNOSTICS,"hunger: %d, max. food_cost: %d, expected hunger: %d",you.hunger, abil.food_cost * 2, expected_hunger);#endif// Safety margin for natural hunger, mutations etc.if (expected_hunger <= 150){mpr("You're too hungry.");crawl_state.zero_turns_taken();return (false);}}if ((tal.which == ABIL_EVOKE_BERSERK || tal.which == ABIL_TROG_BERSERK)&& !berserk_check_wielded_weapon()){crawl_state.zero_turns_taken();return (false);}
if (abil.ability == ABIL_MAPPING&& player_mutation_level(MUT_MAPPING) < 3&& (you.level_type == LEVEL_PANDEMONIUM|| !player_in_mappable_area())){mpr("You feel momentarily disoriented.");return (false);}
if (you.duration[DUR_BREATH_WEAPON] && abil.ability != ABIL_SPIT_ACID){canned_msg(MSG_CANNOT_DO_YET);
beam.range = _calc_breath_ability_range(abil.ability);if (!spell_direction(abild, beam))
// FIXME: This is not the best way to do stuff, because// you have a chance of failing the evocation test, in// which case you'll lose MP, etc.// We should add a pre-failure-test check in general.if (you.hunger_state < HS_SATIATED){mpr("You're too hungry to berserk.");return (false);}else if (!you.can_go_berserk(true))return (false);// only exercise if berserk succeeds// because of the test above, this should always happen,
// Only exercise if berserk succeeds.// Because of the test above, this should always happen,
if (you.duration[DUR_EXHAUSTED]){mpr("You're too exhausted to fly.");return (false);}else if (you.burden_state != BS_UNENCUMBERED){mpr("You're carrying too much weight to fly.");return (false);}elsecast_fly(you.experience_level * 2);
cast_fly(you.experience_level * 2);
int result = check_recital_audience();if (result < 0){mpr("There's no appreciative audience!");return (false);}else if (result < 1){mpr("There's no-one here to preach to!");return (false);}
if (you.level_type != LEVEL_ABYSS){mpr("You aren't in the Abyss!");return (false); // Don't incur costs.}
if (you.level_type == LEVEL_ABYSS){mpr("You're already here.");return (false);}else if (you.level_type == LEVEL_PANDEMONIUM){mpr("That doesn't work from Pandemonium.");return (false);}