3 * @brief Functions related to special abilities.
34 #include "godconduct.h"
35 #include "godprayer.h"
45 #include "mon-place.h"
49 #include "player-stats.h"
55 #include "spl-clouds.h"
56 #include "spl-damage.h"
57 #include "spl-goditem.h"
58 #include "spl-miscast.h"
59 #include "spl-other.h"
60 #include "spl-selfench.h"
61 #include "spl-summoning.h"
62 #include "spl-transloc.h"
65 #include "stringutil.h"
69 #include "transform.h"
75 enum ability_flag_type
77 ABFLAG_NONE = 0x00000000,
78 ABFLAG_BREATH = 0x00000001, // ability uses DUR_BREATH_WEAPON
79 ABFLAG_DELAY = 0x00000002, // ability has its own delay
80 ABFLAG_PAIN = 0x00000004, // ability must hurt player (ie torment)
81 ABFLAG_PIETY = 0x00000008, // ability has its own piety cost
82 ABFLAG_EXHAUSTION = 0x00000010, // fails if you.exhausted
83 ABFLAG_INSTANT = 0x00000020, // doesn't take time to use
84 ABFLAG_PERMANENT_HP = 0x00000040, // costs permanent HPs
85 ABFLAG_PERMANENT_MP = 0x00000080, // costs permanent MPs
86 ABFLAG_CONF_OK = 0x00000100, // can use even if confused
87 ABFLAG_FRUIT = 0x00000200, // ability requires fruit
88 ABFLAG_VARIABLE_FRUIT = 0x00000400, // ability requires fruit or piety
91 ABFLAG_NECRO_MISCAST_MINOR = 0x00002000, // severity 2 necro miscast
94 ABFLAG_LEVEL_DRAIN = 0x00010000, // drains 2 levels
95 ABFLAG_STAT_DRAIN = 0x00020000, // stat drain
96 ABFLAG_ZOTDEF = 0x00040000, // ZotDef ability, w/ appropriate hotkey
97 ABFLAG_SKILL_DRAIN = 0x00080000, // drains skill levels
98 ABFLAG_GOLD = 0x00100000, // costs gold
99 ABFLAG_SACRIFICE = 0x00200000, // sacrifice (Ru)
102 static int _find_ability_slot(const ability_def& abil);
103 static spret_type _do_ability(const ability_def& abil, bool fail);
104 static void _pay_ability_costs(const ability_def& abil, int zpcost);
105 static int _scale_piety_cost(ability_type abil, int original_cost);
106 static string _zd_mons_description_for_ability(const ability_def &abil);
107 static monster_type _monster_for_ability(const ability_def& abil);
110 * This all needs to be split into data/util/show files
111 * and the struct mechanism here needs to be rewritten (again)
112 * along with the display routine to piece the strings
113 * together dynamically ... I'm getting to it now {dlb}
115 * This array corresponds with ::god_gain_power_messages and
116 * ::god_lose_power_messages, which have the same shape.
118 * It makes more sense to think of them as an array
119 * of structs than two arrays that share common index
120 * values -- well, doesn't it? {dlb}
122 * @note Declaring this const messes up externs later, so don't do it!
124 ability_type god_abilities[NUM_GODS][MAX_GOD_ABILITIES] =
127 { ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_NON_ABILITY,
130 { ABIL_ZIN_RECITE, ABIL_ZIN_VITALISATION, ABIL_ZIN_IMPRISON,
131 ABIL_NON_ABILITY, ABIL_ZIN_SANCTUARY },
133 { ABIL_NON_ABILITY, ABIL_TSO_DIVINE_SHIELD, ABIL_NON_ABILITY,
134 ABIL_TSO_CLEANSING_FLAME, ABIL_TSO_SUMMON_DIVINE_WARRIOR },
136 { ABIL_KIKU_RECEIVE_CORPSES, ABIL_NON_ABILITY, ABIL_NON_ABILITY,
137 ABIL_NON_ABILITY, ABIL_KIKU_TORMENT },
139 { ABIL_YRED_ANIMATE_REMAINS_OR_DEAD, ABIL_YRED_RECALL_UNDEAD_SLAVES,
140 ABIL_NON_ABILITY, ABIL_YRED_DRAIN_LIFE, ABIL_YRED_ENSLAVE_SOUL },
142 { ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_NON_ABILITY,
145 { ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_NON_ABILITY,
148 { ABIL_OKAWARU_HEROISM, ABIL_NON_ABILITY, ABIL_NON_ABILITY,
149 ABIL_NON_ABILITY, ABIL_OKAWARU_FINESSE },
151 { ABIL_NON_ABILITY, ABIL_MAKHLEB_MINOR_DESTRUCTION,
152 ABIL_MAKHLEB_LESSER_SERVANT_OF_MAKHLEB, ABIL_MAKHLEB_MAJOR_DESTRUCTION,
153 ABIL_MAKHLEB_GREATER_SERVANT_OF_MAKHLEB },
155 { ABIL_SIF_MUNA_CHANNEL_ENERGY, ABIL_SIF_MUNA_FORGET_SPELL,
156 ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_NON_ABILITY },
158 { ABIL_TROG_BERSERK, ABIL_TROG_REGEN_MR, ABIL_NON_ABILITY,
159 ABIL_TROG_BROTHERS_IN_ARMS, ABIL_NON_ABILITY },
161 { ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_NEMELEX_TRIPLE_DRAW,
162 ABIL_NEMELEX_DEAL_FOUR, ABIL_NEMELEX_STACK_FIVE },
164 { ABIL_ELYVILON_LESSER_HEALING, ABIL_ELYVILON_HEAL_OTHER,
165 ABIL_ELYVILON_PURIFICATION, ABIL_ELYVILON_GREATER_HEALING,
166 ABIL_ELYVILON_DIVINE_VIGOUR },
168 { ABIL_LUGONU_ABYSS_EXIT, ABIL_LUGONU_BEND_SPACE, ABIL_LUGONU_BANISH,
169 ABIL_LUGONU_CORRUPT, ABIL_LUGONU_ABYSS_ENTER },
171 { ABIL_NON_ABILITY, ABIL_BEOGH_SMITING, ABIL_NON_ABILITY,
172 ABIL_BEOGH_RECALL_ORCISH_FOLLOWERS, ABIL_BEOGH_GIFT_ITEM },
174 { ABIL_JIYVA_CALL_JELLY, ABIL_JIYVA_JELLY_PARALYSE, ABIL_NON_ABILITY,
175 ABIL_JIYVA_SLIMIFY, ABIL_JIYVA_CURE_BAD_MUTATION },
177 { ABIL_FEDHAS_EVOLUTION, ABIL_FEDHAS_SUNLIGHT, ABIL_FEDHAS_PLANT_RING,
178 ABIL_FEDHAS_SPAWN_SPORES, ABIL_FEDHAS_RAIN},
180 { ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_CHEIBRIADOS_DISTORTION,
181 ABIL_CHEIBRIADOS_SLOUCH, ABIL_CHEIBRIADOS_TIME_STEP },
183 { ABIL_NON_ABILITY, ABIL_ASHENZARI_SCRYING, ABIL_NON_ABILITY,
184 ABIL_NON_ABILITY, ABIL_ASHENZARI_TRANSFER_KNOWLEDGE },
186 { ABIL_NON_ABILITY, ABIL_DITHMENOS_SHADOW_STEP, ABIL_NON_ABILITY,
187 ABIL_NON_ABILITY, ABIL_DITHMENOS_SHADOW_FORM },
189 { ABIL_GOZAG_POTION_PETITION, ABIL_GOZAG_CALL_MERCHANT,
190 ABIL_GOZAG_BRIBE_BRANCH, ABIL_NON_ABILITY, ABIL_NON_ABILITY },
192 { ABIL_NON_ABILITY, ABIL_QAZLAL_UPHEAVAL, ABIL_QAZLAL_ELEMENTAL_FORCE,
193 ABIL_NON_ABILITY, ABIL_QAZLAL_DISASTER_AREA },
195 { ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_RU_DRAW_OUT_POWER,
196 ABIL_RU_POWER_LEAP, ABIL_RU_APOCALYPSE }
199 // The description screen was way out of date with the actual costs.
200 // This table puts all the information in one place... -- bwr
202 // The five numerical fields are: MP, HP, food, piety and ZP.
203 // Note: food_cost = val + random2avg(val, 2)
204 // piety_cost = val + random2((val + 1) / 2 + 1);
205 // hp cost is in per-mil of maxhp (i.e. 20 = 2% of hp, rounded up)
206 static const ability_def Ability_List[] =
208 // NON_ABILITY should always come first
209 { ABIL_NON_ABILITY, "No ability", 0, 0, 0, 0, 0, ABFLAG_NONE},
210 { ABIL_SPIT_POISON, "Spit Poison", 0, 0, 40, 0, 0, ABFLAG_BREATH},
212 { ABIL_BLINK, "Blink", 0, 50, 50, 0, 0, ABFLAG_NONE},
214 { ABIL_BREATHE_FIRE, "Breathe Fire", 0, 0, 125, 0, 0, ABFLAG_BREATH},
215 { ABIL_BREATHE_FROST, "Breathe Frost", 0, 0, 125, 0, 0, ABFLAG_BREATH},
216 { ABIL_BREATHE_POISON, "Breathe Poison Gas",
217 0, 0, 125, 0, 0, ABFLAG_BREATH},
218 { ABIL_BREATHE_MEPHITIC, "Breathe Noxious Fumes",
219 0, 0, 125, 0, 0, ABFLAG_BREATH},
220 { ABIL_BREATHE_LIGHTNING, "Breathe Lightning",
221 0, 0, 125, 0, 0, ABFLAG_BREATH},
222 { ABIL_BREATHE_POWER, "Breathe Dispelling Energy", 0, 0, 125, 0, 0, ABFLAG_BREATH},
223 { ABIL_BREATHE_STICKY_FLAME, "Breathe Sticky Flame",
224 0, 0, 125, 0, 0, ABFLAG_BREATH},
225 { ABIL_BREATHE_STEAM, "Breathe Steam", 0, 0, 75, 0, 0, ABFLAG_BREATH},
226 { ABIL_TRAN_BAT, "Bat Form", 2, 0, 0, 0, 0, ABFLAG_NONE},
228 { ABIL_SPIT_ACID, "Spit Acid", 0, 0, 125, 0, 0, ABFLAG_BREATH},
230 { ABIL_FLY, "Fly", 3, 0, 100, 0, 0, ABFLAG_NONE},
231 { ABIL_STOP_FLYING, "Stop Flying", 0, 0, 0, 0, 0, ABFLAG_NONE},
232 { ABIL_HELLFIRE, "Hellfire", 0, 150, 200, 0, 0, ABFLAG_NONE},
234 { ABIL_DELAYED_FIREBALL, "Release Delayed Fireball",
235 0, 0, 0, 0, 0, ABFLAG_INSTANT},
236 { ABIL_STOP_SINGING, "Stop Singing",
237 0, 0, 0, 0, 0, ABFLAG_NONE},
238 { ABIL_MUMMY_RESTORATION, "Self-Restoration",
239 1, 0, 0, 0, 0, ABFLAG_PERMANENT_MP},
241 { ABIL_DIG, "Dig", 0, 0, 0, 0, 0, ABFLAG_INSTANT},
242 { ABIL_SHAFT_SELF, "Shaft Self", 0, 0, 250, 0, 0, ABFLAG_DELAY},
244 // EVOKE abilities use Evocations and come from items.
245 // Teleportation and Blink can also come from mutations
246 // so we have to distinguish them (see above). The off items
247 // below are labeled EVOKE because they only work now if the
248 // player has an item with the evocable power (not just because
249 // you used a wand, potion, or miscast effect). I didn't see
250 // any reason to label them as "Evoke" in the text, they don't
251 // use or train Evocations (the others do). -- bwr
252 { ABIL_EVOKE_TELEPORTATION, "Evoke Teleportation",
253 3, 0, 200, 0, 0, ABFLAG_NONE},
254 { ABIL_EVOKE_BLINK, "Evoke Blink", 1, 0, 50, 0, 0, ABFLAG_NONE},
255 { ABIL_RECHARGING, "Device Recharging", 1, 0, 0, 0, 0, ABFLAG_PERMANENT_MP},
257 { ABIL_EVOKE_BERSERK, "Evoke Berserk Rage", 0, 0, 0, 0, 0, ABFLAG_NONE},
259 { ABIL_EVOKE_TURN_INVISIBLE, "Evoke Invisibility",
260 2, 0, 250, 0, 0, ABFLAG_NONE},
261 { ABIL_EVOKE_TURN_VISIBLE, "Turn Visible", 0, 0, 0, 0, 0, ABFLAG_NONE},
262 { ABIL_EVOKE_FLIGHT, "Evoke Flight", 1, 0, 100, 0, 0, ABFLAG_NONE},
263 { ABIL_EVOKE_FOG, "Evoke Fog", 2, 0, 250, 0, 0, ABFLAG_NONE},
264 { ABIL_EVOKE_TELEPORT_CONTROL, "Evoke Teleport Control", 4, 0, 200, 0, 0, ABFLAG_NONE},
265 { ABIL_EVOKE_TWISTER, "Evoke Twister", 10, 0, 200, 0, 0, ABFLAG_NONE},
267 { ABIL_END_TRANSFORMATION, "End Transformation", 0, 0, 0, 0, 0, ABFLAG_NONE},
271 { ABIL_ZIN_RECITE, "Recite", 0, 0, 0, 0, 0, ABFLAG_BREATH},
272 { ABIL_ZIN_VITALISATION, "Vitalisation", 0, 0, 0, 1, 0, ABFLAG_NONE},
273 { ABIL_ZIN_IMPRISON, "Imprison", 5, 0, 125, 4, 0, ABFLAG_NONE},
274 { ABIL_ZIN_SANCTUARY, "Sanctuary", 7, 0, 150, 15, 0, ABFLAG_NONE},
275 { ABIL_ZIN_CURE_ALL_MUTATIONS, "Cure All Mutations",
276 0, 0, 0, 0, 0, ABFLAG_NONE},
279 { ABIL_TSO_DIVINE_SHIELD, "Divine Shield", 3, 0, 50, 2, 0, ABFLAG_NONE},
280 { ABIL_TSO_CLEANSING_FLAME, "Cleansing Flame",
281 5, 0, 100, 2, 0, ABFLAG_NONE},
282 { ABIL_TSO_SUMMON_DIVINE_WARRIOR, "Summon Divine Warrior",
283 8, 0, 150, 5, 0, ABFLAG_NONE},
286 { ABIL_KIKU_RECEIVE_CORPSES, "Receive Corpses",
287 3, 0, 50, 2, 0, ABFLAG_NONE},
288 { ABIL_KIKU_TORMENT, "Torment", 4, 0, 0, 8, 0, ABFLAG_NONE},
291 { ABIL_YRED_INJURY_MIRROR, "Injury Mirror", 0, 0, 0, 0, 0, ABFLAG_PIETY},
292 { ABIL_YRED_ANIMATE_REMAINS, "Animate Remains",
293 2, 0, 50, 0, 0, ABFLAG_NONE},
294 { ABIL_YRED_RECALL_UNDEAD_SLAVES, "Recall Undead Slaves",
295 2, 0, 50, 0, 0, ABFLAG_NONE},
296 { ABIL_YRED_ANIMATE_DEAD, "Animate Dead", 2, 0, 50, 0, 0, ABFLAG_NONE},
297 { ABIL_YRED_DRAIN_LIFE, "Drain Life", 6, 0, 200, 2, 0, ABFLAG_NONE},
298 { ABIL_YRED_ENSLAVE_SOUL, "Enslave Soul", 8, 0, 150, 4, 0, ABFLAG_NONE},
299 // Placeholder for Animate Remains or Animate Dead.
300 { ABIL_YRED_ANIMATE_REMAINS_OR_DEAD, "Animate Remains or Dead",
301 2, 0, 100, 0, 0, ABFLAG_NONE},
304 { ABIL_OKAWARU_HEROISM, "Heroism", 2, 0, 50, 2, 0, ABFLAG_NONE},
305 { ABIL_OKAWARU_FINESSE, "Finesse", 5, 0, 100, 4, 0, ABFLAG_NONE},
308 { ABIL_MAKHLEB_MINOR_DESTRUCTION, "Minor Destruction",
309 0, scaling_cost::fixed(1), 20, 0, 0, ABFLAG_NONE},
310 { ABIL_MAKHLEB_LESSER_SERVANT_OF_MAKHLEB, "Lesser Servant of Makhleb",
311 0, scaling_cost::fixed(4), 50, 2, 0, ABFLAG_NONE},
312 { ABIL_MAKHLEB_MAJOR_DESTRUCTION, "Major Destruction",
313 0, scaling_cost::fixed(6), 100, generic_cost::range(0, 1), 0, ABFLAG_NONE},
314 { ABIL_MAKHLEB_GREATER_SERVANT_OF_MAKHLEB, "Greater Servant of Makhleb",
315 0, scaling_cost::fixed(10), 100, 5, 0, ABFLAG_NONE},
318 { ABIL_SIF_MUNA_CHANNEL_ENERGY, "Channel Energy",
319 0, 0, 100, 0, 0, ABFLAG_NONE},
320 { ABIL_SIF_MUNA_FORGET_SPELL, "Forget Spell", 5, 0, 0, 8, 0, ABFLAG_NONE},
323 { ABIL_TROG_BURN_SPELLBOOKS, "Burn Spellbooks",
324 0, 0, 10, 0, 0, ABFLAG_NONE},
325 { ABIL_TROG_BERSERK, "Berserk", 0, 0, 200, 0, 0, ABFLAG_NONE},
326 { ABIL_TROG_REGEN_MR, "Trog's Hand",
327 0, 0, 50, generic_cost::range(2, 3), 0, ABFLAG_NONE},
328 { ABIL_TROG_BROTHERS_IN_ARMS, "Brothers in Arms",
329 0, 0, 100, generic_cost::range(5, 6), 0, ABFLAG_NONE},
332 { ABIL_ELYVILON_LIFESAVING, "Divine Protection",
333 0, 0, 0, 0, 0, ABFLAG_NONE},
334 { ABIL_ELYVILON_LESSER_HEALING, "Lesser Healing",
335 1, 0, 100, generic_cost::range(0, 1), 0, ABFLAG_CONF_OK},
336 { ABIL_ELYVILON_HEAL_OTHER, "Heal Other",
337 2, 0, 250, 2, 0, ABFLAG_NONE},
338 { ABIL_ELYVILON_PURIFICATION, "Purification", 3, 0, 300, 3, 0,
340 { ABIL_ELYVILON_GREATER_HEALING, "Greater Healing",
341 2, 0, 250, 3, 0, ABFLAG_CONF_OK},
342 { ABIL_ELYVILON_DIVINE_VIGOUR, "Divine Vigour", 0, 0, 600, 6, 0,
346 { ABIL_LUGONU_ABYSS_EXIT, "Depart the Abyss",
347 1, 0, 150, 10, 0, ABFLAG_NONE},
348 { ABIL_LUGONU_BEND_SPACE, "Bend Space", 1, 0, 50, 0, 0, ABFLAG_PAIN},
349 { ABIL_LUGONU_BANISH, "Banish",
350 4, 0, 200, generic_cost::range(3, 4), 0, ABFLAG_NONE},
351 { ABIL_LUGONU_CORRUPT, "Corrupt",
352 7, scaling_cost::fixed(5), 500, generic_cost::range(10, 14), 0, ABFLAG_NONE},
353 { ABIL_LUGONU_ABYSS_ENTER, "Enter the Abyss",
354 9, 0, 500, generic_cost::fixed(35), 0, ABFLAG_PAIN},
357 { ABIL_NEMELEX_TRIPLE_DRAW, "Triple Draw", 2, 0, 100, 2, 0, ABFLAG_NONE},
358 { ABIL_NEMELEX_DEAL_FOUR, "Deal Four", 8, 0, 200, 8, 0, ABFLAG_NONE},
359 { ABIL_NEMELEX_STACK_FIVE, "Stack Five", 5, 0, 250, 10, 0, ABFLAG_NONE},
362 { ABIL_BEOGH_SMITING, "Smiting",
363 3, 0, 80, generic_cost::fixed(3), 0, ABFLAG_NONE},
364 { ABIL_BEOGH_RECALL_ORCISH_FOLLOWERS, "Recall Orcish Followers",
365 2, 0, 50, 0, 0, ABFLAG_NONE},
366 { ABIL_BEOGH_GIFT_ITEM, "Give Item to Named Follower",
367 0, 0, 0, 0, 0, ABFLAG_NONE},
370 { ABIL_JIYVA_CALL_JELLY, "Request Jelly", 2, 0, 20, 1, 0, ABFLAG_NONE},
371 { ABIL_JIYVA_JELLY_PARALYSE, "Jelly Paralyse", 0, 0, 0, 0, 0, ABFLAG_PIETY},
372 { ABIL_JIYVA_SLIMIFY, "Slimify", 4, 0, 100, 8, 0, ABFLAG_NONE},
373 { ABIL_JIYVA_CURE_BAD_MUTATION, "Cure Bad Mutation",
374 8, 0, 200, 15, 0, ABFLAG_NONE},
377 { ABIL_FEDHAS_EVOLUTION, "Evolution", 2, 0, 0, 0, 0, ABFLAG_VARIABLE_FRUIT},
378 { ABIL_FEDHAS_SUNLIGHT, "Sunlight", 2, 0, 50, 0, 0, ABFLAG_NONE},
379 { ABIL_FEDHAS_PLANT_RING, "Growth", 2, 0, 0, 0, 0, ABFLAG_FRUIT},
380 { ABIL_FEDHAS_SPAWN_SPORES, "Reproduction", 4, 0, 100, 1, 0, ABFLAG_NONE},
381 { ABIL_FEDHAS_RAIN, "Rain", 4, 0, 150, 4, 0, ABFLAG_NONE},
384 { ABIL_CHEIBRIADOS_TIME_BEND, "Bend Time", 3, 0, 50, 1, 0, ABFLAG_NONE},
385 { ABIL_CHEIBRIADOS_DISTORTION, "Temporal Distortion",
386 4, 0, 200, 3, 0, ABFLAG_INSTANT},
387 { ABIL_CHEIBRIADOS_SLOUCH, "Slouch", 5, 0, 100, 8, 0, ABFLAG_NONE},
388 { ABIL_CHEIBRIADOS_TIME_STEP, "Step From Time",
389 10, 0, 200, 10, 0, ABFLAG_NONE},
392 { ABIL_ASHENZARI_SCRYING, "Scrying",
393 4, 0, 50, generic_cost::range(2, 3), 0, ABFLAG_INSTANT},
394 { ABIL_ASHENZARI_TRANSFER_KNOWLEDGE, "Transfer Knowledge",
395 0, 0, 0, 20, 0, ABFLAG_NONE},
396 { ABIL_ASHENZARI_END_TRANSFER, "End Transfer Knowledge",
397 0, 0, 0, 0, 0, ABFLAG_NONE},
400 { ABIL_DITHMENOS_SHADOW_STEP, "Shadow Step",
401 4, 0, 0, 4, 0, ABFLAG_NONE },
402 { ABIL_DITHMENOS_SHADOW_FORM, "Shadow Form",
403 9, 0, 0, 10, 0, ABFLAG_SKILL_DRAIN },
406 { ABIL_RU_DRAW_OUT_POWER, "Draw Out Power",
407 0, 0, 0, 0, 0, ABFLAG_EXHAUSTION|ABFLAG_SKILL_DRAIN|ABFLAG_CONF_OK },
408 { ABIL_RU_POWER_LEAP, "Power Leap",
409 5, 0, 0, 0, 0, ABFLAG_EXHAUSTION },
410 { ABIL_RU_APOCALYPSE, "Apocalypse",
411 8, 0, 0, 0, 0, ABFLAG_EXHAUSTION|ABFLAG_SKILL_DRAIN },
413 { ABIL_RU_SACRIFICE_PURITY, "Sacrifice Purity",
414 0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
415 { ABIL_RU_SACRIFICE_WORDS, "Sacrifice Words",
416 0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
417 { ABIL_RU_SACRIFICE_DRINK, "Sacrifice Drink",
418 0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
419 { ABIL_RU_SACRIFICE_ESSENCE, "Sacrifice Essence",
420 0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
421 { ABIL_RU_SACRIFICE_HEALTH, "Sacrifice Health",
422 0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
423 { ABIL_RU_SACRIFICE_STEALTH, "Sacrifice Stealth",
424 0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
425 { ABIL_RU_SACRIFICE_ARTIFICE, "Sacrifice Artifice",
426 0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
427 { ABIL_RU_SACRIFICE_LOVE, "Sacrifice Love",
428 0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
429 { ABIL_RU_SACRIFICE_COURAGE, "Sacrifice Courage",
430 0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
431 { ABIL_RU_SACRIFICE_ARCANA, "Sacrifice Arcana",
432 0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
433 { ABIL_RU_SACRIFICE_NIMBLENESS, "Sacrifice Nimbleness",
434 0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
435 { ABIL_RU_SACRIFICE_DURABILITY, "Sacrifice Durability",
436 0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
437 { ABIL_RU_SACRIFICE_HAND, "Sacrifice a Hand",
438 0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
439 { ABIL_RU_SACRIFICE_EXPERIENCE, "Sacrifice Experience",
440 0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
441 { ABIL_RU_SACRIFICE_SKILL, "Sacrifice Skill",
442 0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
443 { ABIL_RU_REJECT_SACRIFICES, "Reject Sacrifices",
444 0, 0, 0, 0, 0, ABFLAG_NONE },
447 { ABIL_GOZAG_POTION_PETITION, "Potion Petition",
448 0, 0, 0, 0, 0, ABFLAG_GOLD },
449 { ABIL_GOZAG_CALL_MERCHANT, "Call Merchant",
450 0, 0, 0, 0, 0, ABFLAG_GOLD },
451 { ABIL_GOZAG_BRIBE_BRANCH, "Bribe Branch",
452 0, 0, 0, 0, 0, ABFLAG_GOLD },
455 { ABIL_QAZLAL_UPHEAVAL, "Upheaval", 4, 0, 0, 3, 0, ABFLAG_NONE },
456 { ABIL_QAZLAL_ELEMENTAL_FORCE, "Elemental Force",
457 6, 0, 0, 6, 0, ABFLAG_NONE },
458 { ABIL_QAZLAL_DISASTER_AREA, "Disaster Area", 7, 0, 0,
459 generic_cost::range(10, 14), 0, ABFLAG_NONE },
461 { ABIL_STOP_RECALL, "Stop Recall", 0, 0, 0, 0, 0, ABFLAG_NONE},
463 // zot defence abilities
464 { ABIL_MAKE_FUNGUS, "Make mushroom circle", 0, 0, 0, 0, 10, ABFLAG_ZOTDEF},
465 { ABIL_MAKE_PLANT, "Make plant", 0, 0, 0, 0, 2, ABFLAG_ZOTDEF},
466 { ABIL_MAKE_OKLOB_SAPLING, "Make oklob sapling", 0, 0, 0, 0, 60, ABFLAG_ZOTDEF},
467 { ABIL_MAKE_BURNING_BUSH, "Make burning bush", 0, 0, 0, 0, 200, ABFLAG_ZOTDEF},
468 { ABIL_MAKE_OKLOB_PLANT, "Make oklob plant", 0, 0, 0, 0, 250, ABFLAG_ZOTDEF},
469 { ABIL_MAKE_ICE_STATUE, "Make ice statue", 0, 0, 0, 0, 2000, ABFLAG_ZOTDEF},
470 { ABIL_MAKE_OCS, "Make crystal statue", 0, 0, 0, 0, 2000, ABFLAG_ZOTDEF},
471 { ABIL_MAKE_OBSIDIAN_STATUE, "Make obsidian statue", 0, 0, 0, 0, 3000, ABFLAG_ZOTDEF},
472 { ABIL_MAKE_CURSE_SKULL, "Make curse skull",
473 0, 0, 600, 0, 10000, ABFLAG_ZOTDEF|ABFLAG_NECRO_MISCAST_MINOR},
474 { ABIL_MAKE_TELEPORT, "Zot-teleport", 0, 0, 0, 0, 2, ABFLAG_ZOTDEF},
475 { ABIL_MAKE_ARROW_TRAP, "Make arrow trap", 0, 0, 0, 0, 30, ABFLAG_ZOTDEF},
476 { ABIL_MAKE_BOLT_TRAP, "Make bolt trap", 0, 0, 0, 0, 300, ABFLAG_ZOTDEF},
477 { ABIL_MAKE_SPEAR_TRAP, "Make spear trap", 0, 0, 0, 0, 50, ABFLAG_ZOTDEF},
478 { ABIL_MAKE_NEEDLE_TRAP, "Make needle trap", 0, 0, 0, 0, 30, ABFLAG_ZOTDEF},
479 { ABIL_MAKE_NET_TRAP, "Make net trap", 0, 0, 0, 0, 2, ABFLAG_ZOTDEF},
480 { ABIL_MAKE_ALARM_TRAP, "Make alarm trap", 0, 0, 0, 0, 2, ABFLAG_ZOTDEF},
481 { ABIL_MAKE_BLADE_TRAP, "Make blade trap", 0, 0, 0, 0, 3000, ABFLAG_ZOTDEF},
482 { ABIL_MAKE_OKLOB_CIRCLE, "Make oklob circle", 0, 0, 0, 0, 1000, ABFLAG_ZOTDEF},
483 { ABIL_MAKE_ACQUIRE_GOLD, "Acquire gold",
484 0, 0, 0, 0, 0, ABFLAG_ZOTDEF|ABFLAG_LEVEL_DRAIN},
485 { ABIL_MAKE_ACQUIREMENT, "Acquirement",
486 0, 0, 0, 0, 0, ABFLAG_ZOTDEF|ABFLAG_LEVEL_DRAIN},
487 { ABIL_MAKE_WATER, "Make water", 0, 0, 0, 0, 10, ABFLAG_ZOTDEF},
488 { ABIL_MAKE_LIGHTNING_SPIRE, "Make lightning spire", 0, 0, 0, 0, 100, ABFLAG_ZOTDEF},
489 { ABIL_MAKE_BAZAAR, "Make bazaar",
490 0, 30, 0, 0, 100, ABFLAG_ZOTDEF|ABFLAG_PERMANENT_HP},
491 { ABIL_MAKE_ALTAR, "Make altar", 0, 0, 0, 0, 50, ABFLAG_ZOTDEF},
492 { ABIL_MAKE_GRENADES, "Make grenades", 0, 0, 0, 0, 2, ABFLAG_ZOTDEF},
493 { ABIL_REMOVE_CURSE, "Remove Curse",
494 0, 0, 0, 0, 0, ABFLAG_ZOTDEF|ABFLAG_STAT_DRAIN},
496 { ABIL_RENOUNCE_RELIGION, "Renounce Religion", 0, 0, 0, 0, 0, ABFLAG_NONE},
497 { ABIL_CONVERT_TO_BEOGH, "Convert to Beogh", 0, 0, 0, 0, 0, ABFLAG_NONE},
500 const ability_def& get_ability_def(ability_type abil)
502 for (const ability_def &ab_def : Ability_List)
503 if (ab_def.ability == abil)
506 return Ability_List[0];
510 * Is there a valid ability with a name matching that given?
512 * @param key The name in question. (Not case sensitive.)
513 * @return true if such an ability exists; false if not.
515 bool string_matches_ability_name(const string& key)
517 return ability_by_name(key) != ABIL_NON_ABILITY;
521 * Find an ability whose name matches the given key.
523 * @param name The name in question. (Not case sensitive.)
524 * @return The enum of the relevant ability, if there was one; else
527 ability_type ability_by_name(const string &key)
529 for (const auto &abil : Ability_List)
531 if (abil.ability == ABIL_NON_ABILITY)
534 // don't display zot abilties outside zotdef
535 if ((abil.flags & ABFLAG_ZOTDEF) && !crawl_state.game_is_zotdef())
538 const string name = lowercase_string(ability_name(abil.ability));
539 if (name == lowercase_string(key))
543 return ABIL_NON_ABILITY;
546 string print_abilities()
548 string text = "\n<w>a:</w> ";
550 const vector<talent> talents = your_talents(false);
553 text += "no special abilities";
556 for (unsigned int i = 0; i < talents.size(); ++i)
560 text += ability_name(talents[i].which);
567 static monster_type _monster_for_ability(const ability_def& abil)
569 monster_type mtyp = MONS_PROGRAM_BUG;
570 switch (abil.ability)
572 case ABIL_MAKE_PLANT: mtyp = MONS_PLANT; break;
573 case ABIL_MAKE_FUNGUS: mtyp = MONS_FUNGUS; break;
574 case ABIL_MAKE_OKLOB_SAPLING: mtyp = MONS_OKLOB_SAPLING; break;
575 case ABIL_MAKE_OKLOB_CIRCLE:
576 case ABIL_MAKE_OKLOB_PLANT: mtyp = MONS_OKLOB_PLANT; break;
577 case ABIL_MAKE_BURNING_BUSH: mtyp = MONS_BURNING_BUSH; break;
578 case ABIL_MAKE_LIGHTNING_SPIRE: mtyp = MONS_LIGHTNING_SPIRE; break;
579 case ABIL_MAKE_ICE_STATUE: mtyp = MONS_ICE_STATUE; break;
580 case ABIL_MAKE_OCS: mtyp = MONS_ORANGE_STATUE; break;
581 case ABIL_MAKE_OBSIDIAN_STATUE: mtyp = MONS_OBSIDIAN_STATUE; break;
582 case ABIL_MAKE_CURSE_SKULL: mtyp = MONS_CURSE_SKULL; break;
584 mprf("DEBUG: NO RELEVANT MONSTER FOR %d", abil.ability);
590 static string _zd_mons_description_for_ability(const ability_def &abil)
592 switch (abil.ability)
594 case ABIL_MAKE_PLANT:
595 return "Tendrils and shoots erupt from the earth and gnarl into the form of a plant.";
596 case ABIL_MAKE_OKLOB_SAPLING:
597 return "A rhizome shoots up through the ground and merges with vitriolic spirits in the atmosphere.";
598 case ABIL_MAKE_OKLOB_PLANT:
599 return "A rhizome shoots up through the ground and merges with vitriolic spirits in the atmosphere.";
600 case ABIL_MAKE_BURNING_BUSH:
601 return "Blackened shoots writhe from the ground and burst into flame!";
602 case ABIL_MAKE_ICE_STATUE:
603 return "Water vapor collects and crystallises into an icy humanoid shape.";
605 return "Quartz juts from the ground and forms a humanoid shape. You smell citrus.";
606 case ABIL_MAKE_OBSIDIAN_STATUE:
607 return "Molten obsidian falls from the ceiling and solidifies into a vaguely humanoid shape.";
608 case ABIL_MAKE_CURSE_SKULL:
609 return "You sculpt a terrible being from the primitive principle of evil.";
610 case ABIL_MAKE_LIGHTNING_SPIRE:
611 return "You mount a charged rod inside a coil.";
617 static int _count_relevant_monsters(const ability_def& abil)
619 monster_type mtyp = _monster_for_ability(abil);
620 if (mtyp == MONS_PROGRAM_BUG)
622 return count_monsters(mtyp, true); // Friendly ones only
625 static trap_type _trap_for_ability(const ability_def& abil)
627 switch (abil.ability)
629 case ABIL_MAKE_ARROW_TRAP: return TRAP_ARROW;
630 case ABIL_MAKE_BOLT_TRAP: return TRAP_BOLT;
631 case ABIL_MAKE_SPEAR_TRAP: return TRAP_SPEAR;
632 case ABIL_MAKE_NEEDLE_TRAP: return TRAP_NEEDLE;
633 case ABIL_MAKE_NET_TRAP: return TRAP_NET;
634 case ABIL_MAKE_ALARM_TRAP: return TRAP_ALARM;
635 case ABIL_MAKE_BLADE_TRAP: return TRAP_BLADE;
636 default: return TRAP_UNASSIGNED;
640 // Scale the zp cost by the number of friendly monsters
641 // of that type. Each successive critter costs 20% more
642 // than the last one, after the first two.
643 static int _zp_cost(const ability_def& abil)
645 int cost = abil.zp_cost;
646 int scale10 = 0; // number of times to scale up by 10%
647 int scale20 = 0; // number of times to scale up by 20%
649 switch (abil.ability)
654 // Monster type 1: reasonably generous
655 case ABIL_MAKE_PLANT:
656 case ABIL_MAKE_FUNGUS:
657 case ABIL_MAKE_OKLOB_SAPLING:
658 case ABIL_MAKE_OKLOB_PLANT:
659 case ABIL_MAKE_OKLOB_CIRCLE:
660 case ABIL_MAKE_BURNING_BUSH:
661 case ABIL_MAKE_LIGHTNING_SPIRE:
662 num = _count_relevant_monsters(abil);
663 // special case for oklob circles
664 if (abil.ability == ABIL_MAKE_OKLOB_CIRCLE)
666 // ... and for harmless stuff
667 else if (abil.ability == ABIL_MAKE_PLANT
668 || abil.ability == ABIL_MAKE_FUNGUS)
672 num -= 2; // first two are base cost
674 scale10 = min(num, 10); // next 10 at 10% increment
675 scale20 = num - scale10; // after that at 20% increment
678 // Monster type 2: less generous
679 case ABIL_MAKE_ICE_STATUE:
681 num = _count_relevant_monsters(abil);
682 num -= 2; // first two are base cost
683 scale20 = max(num, 0); // after first two, 20% increment
686 // Monster type 3: least generous
687 case ABIL_MAKE_OBSIDIAN_STATUE:
688 case ABIL_MAKE_CURSE_SKULL:
689 scale20 = _count_relevant_monsters(abil); // scale immediately
693 case ABIL_MAKE_ARROW_TRAP:
694 case ABIL_MAKE_BOLT_TRAP:
695 case ABIL_MAKE_SPEAR_TRAP:
696 case ABIL_MAKE_NEEDLE_TRAP:
697 case ABIL_MAKE_NET_TRAP:
698 case ABIL_MAKE_ALARM_TRAP:
699 num = count_traps(_trap_for_ability(abil));
700 scale10 = max(num-5, 0); // First 5 at base cost
703 case ABIL_MAKE_BLADE_TRAP:
704 scale10 = count_traps(TRAP_BLADE); // Max of 18-ish at base cost 3000
708 float c = cost; // stave off round-off errors
709 for (; scale10 > 0; scale10--)
711 for (; scale20 > 0; scale20--)
717 int get_gold_cost(ability_type ability)
721 case ABIL_GOZAG_CALL_MERCHANT:
722 return gozag_price_for_shop(true);
723 case ABIL_GOZAG_POTION_PETITION:
724 return gozag_potion_price();
725 case ABIL_GOZAG_BRIBE_BRANCH:
726 return GOZAG_BRIBE_AMOUNT;
732 const string make_cost_description(ability_type ability)
734 const ability_def& abil = get_ability_def(ability);
738 ret += make_stringf(", %d %sMP", abil.mp_cost,
739 abil.flags & ABFLAG_PERMANENT_MP ? "Permanent " : "");
744 ret += make_stringf(", %d %sHP", abil.hp_cost.cost(you.hp_max),
745 abil.flags & ABFLAG_PERMANENT_HP ? "Permanent " : "");
749 ret += make_stringf(", %d ZP", (int)_zp_cost(abil));
751 if (abil.food_cost && !you_foodless(true)
752 && (you.undead_state() != US_SEMI_UNDEAD
753 || you.hunger_state > HS_STARVING))
755 ret += ", Hunger"; // randomised and exact amount hidden from player
758 if (abil.piety_cost || abil.flags & ABFLAG_PIETY)
759 ret += ", Piety"; // randomised and exact amount hidden from player
761 if (abil.flags & ABFLAG_BREATH)
764 if (abil.flags & ABFLAG_DELAY)
767 if (abil.flags & ABFLAG_PAIN)
770 if (abil.flags & ABFLAG_EXHAUSTION)
771 ret += ", Exhaustion";
773 if (abil.flags & ABFLAG_INSTANT)
774 ret += ", Instant"; // not really a cost, more of a bonus - bwr
776 if (abil.flags & ABFLAG_FRUIT)
779 if (abil.flags & ABFLAG_VARIABLE_FRUIT)
780 ret += ", Fruit or Piety";
782 if (abil.flags & ABFLAG_LEVEL_DRAIN)
783 ret += ", Level drain";
785 if (abil.flags & ABFLAG_STAT_DRAIN)
786 ret += ", Stat drain";
788 if (abil.flags & ABFLAG_SKILL_DRAIN)
789 ret += ", Skill drain";
791 if (abil.flags & ABFLAG_GOLD)
793 const int amount = get_gold_cost(ability);
795 ret += make_stringf(", %d Gold", amount);
796 else if (ability == ABIL_GOZAG_POTION_PETITION)
802 if (abil.flags & ABFLAG_SACRIFICE)
805 const string prefix = "Sacrifice ";
806 ret += string(ability_name(ability)).substr(prefix.size());
807 ret += ru_sac_text(ability);
810 // If we haven't output anything so far, then the effect has no cost
818 static string _get_piety_amount_str(int value)
820 return value > 15 ? "extremely large" :
821 value > 10 ? "large" :
822 value > 5 ? "moderate" :
826 static const string _detailed_cost_description(ability_type ability)
828 const ability_def& abil = get_ability_def(ability);
830 vector<string> values;
833 bool have_cost = false;
834 ret << "This ability costs: ";
836 if (abil.mp_cost > 0)
839 if (abil.flags & ABFLAG_PERMANENT_MP)
840 ret << "\nMax MP : ";
848 if (abil.flags & ABFLAG_PERMANENT_HP)
849 ret << "\nMax HP : ";
852 ret << abil.hp_cost.cost(you.hp_max);
861 if (abil.food_cost && !you_foodless(true)
862 && (you.undead_state() != US_SEMI_UNDEAD
863 || you.hunger_state > HS_STARVING))
866 ret << "\nHunger : ";
867 ret << hunger_cost_string(abil.food_cost + abil.food_cost / 2);
870 if (abil.piety_cost || abil.flags & ABFLAG_PIETY)
874 if (abil.flags & ABFLAG_PIETY)
878 int avgcost = abil.piety_cost.base + abil.piety_cost.add / 2;
879 ret << _get_piety_amount_str(avgcost);
883 if (abil.flags & ABFLAG_GOLD)
887 int gold_amount = get_gold_cost(ability);
890 else if (ability == ABIL_GOZAG_POTION_PETITION)
899 if (abil.flags & ABFLAG_BREATH)
900 ret << "\nYou must catch your breath between uses of this ability.";
902 if (abil.flags & ABFLAG_DELAY)
903 ret << "\nIt takes some time before being effective.";
905 if (abil.flags & ABFLAG_PAIN)
906 ret << "\nUsing this ability will hurt you.";
908 if (abil.flags & ABFLAG_EXHAUSTION)
909 ret << "\nIt cannot be used when exhausted.";
911 if (abil.flags & ABFLAG_INSTANT)
912 ret << "\nIt is instantaneous.";
914 if (abil.flags & ABFLAG_CONF_OK)
915 ret << "\nYou can use it even if confused.";
917 if (abil.flags & ABFLAG_LEVEL_DRAIN)
918 ret << "\nIt will lower your experience level by one when used.";
920 if (abil.flags & ABFLAG_STAT_DRAIN)
921 ret << "\nIt will temporarily drain your strength, intelligence or dexterity when used.";
923 if (abil.flags & ABFLAG_SKILL_DRAIN)
924 ret << "\nIt will temporarily drain your skills when used.";
929 static ability_type _fixup_ability(ability_type ability)
933 case ABIL_YRED_ANIMATE_REMAINS_OR_DEAD:
934 // Placeholder for Animate Remains or Animate Dead.
935 if (yred_can_animate_dead())
936 return ABIL_YRED_ANIMATE_DEAD;
938 return ABIL_YRED_ANIMATE_REMAINS;
940 case ABIL_YRED_RECALL_UNDEAD_SLAVES:
941 case ABIL_BEOGH_RECALL_ORCISH_FOLLOWERS:
942 if (!you.recall_list.empty())
943 return ABIL_STOP_RECALL;
946 case ABIL_EVOKE_BERSERK:
947 case ABIL_TROG_BERSERK:
948 if (you.is_lifeless_undead(false)
949 || you.species == SP_FORMICID)
951 return ABIL_NON_ABILITY;
955 case ABIL_OKAWARU_FINESSE:
957 case ABIL_EVOKE_BLINK:
958 if (you.species == SP_FORMICID)
959 return ABIL_NON_ABILITY;
968 talent get_talent(ability_type ability, bool check_confused)
970 ASSERT(ability != ABIL_NON_ABILITY);
973 // Placeholder handling, part 1: The ability we have might be a
974 // placeholder, so convert it into its corresponding ability before
975 // doing anything else, so that we'll handle its flags properly.
976 result.which = _fixup_ability(ability);
978 const ability_def &abil = get_ability_def(result.which);
985 if (you.confused() && !testbits(abil.flags, ABFLAG_CONF_OK))
987 // Initialize these so compilers don't complain.
988 result.is_invocation = 0;
989 result.is_zotdef = 0;
993 result.which = ABIL_NON_ABILITY;
998 // Look through the table to see if there's a preference, else find
999 // a new empty slot for this ability. - bwr
1000 const int index = _find_ability_slot(abil);
1002 result.hotkey = index_to_letter(index);
1004 result.hotkey = 0; // means 'find later on'
1008 // begin spell abilities
1009 case ABIL_DELAYED_FIREBALL:
1010 case ABIL_MUMMY_RESTORATION:
1011 case ABIL_STOP_SINGING:
1015 // begin zot defence abilities
1016 case ABIL_MAKE_FUNGUS:
1017 case ABIL_MAKE_PLANT:
1018 case ABIL_MAKE_OKLOB_PLANT:
1019 case ABIL_MAKE_OKLOB_SAPLING:
1020 case ABIL_MAKE_BURNING_BUSH:
1021 case ABIL_MAKE_ICE_STATUE:
1023 case ABIL_MAKE_OBSIDIAN_STATUE:
1024 case ABIL_MAKE_CURSE_SKULL:
1025 case ABIL_MAKE_TELEPORT:
1026 case ABIL_MAKE_ARROW_TRAP:
1027 case ABIL_MAKE_BOLT_TRAP:
1028 case ABIL_MAKE_SPEAR_TRAP:
1029 case ABIL_MAKE_NEEDLE_TRAP:
1030 case ABIL_MAKE_NET_TRAP:
1031 case ABIL_MAKE_ALARM_TRAP:
1032 case ABIL_MAKE_BLADE_TRAP:
1033 case ABIL_MAKE_OKLOB_CIRCLE:
1034 case ABIL_MAKE_ACQUIRE_GOLD:
1035 case ABIL_MAKE_ACQUIREMENT:
1036 case ABIL_MAKE_WATER:
1037 case ABIL_MAKE_LIGHTNING_SPIRE:
1038 case ABIL_MAKE_BAZAAR:
1039 case ABIL_MAKE_ALTAR:
1040 case ABIL_MAKE_GRENADES:
1041 case ABIL_REMOVE_CURSE:
1045 // begin species abilities - some are mutagenic, too {dlb}
1046 case ABIL_SPIT_POISON:
1048 - 10 * player_mutation_level(MUT_SPIT_POISON)
1049 - you.experience_level;
1052 case ABIL_BREATHE_FIRE:
1053 failure = ((you.species == SP_RED_DRACONIAN) ? 30 : 50)
1054 - 10 * player_mutation_level(MUT_BREATHE_FLAMES)
1055 - you.experience_level;
1057 if (you.form == TRAN_DRAGON)
1060 case ABIL_BREATHE_FROST:
1061 case ABIL_BREATHE_POISON:
1062 case ABIL_SPIT_ACID:
1063 case ABIL_BREATHE_LIGHTNING:
1064 case ABIL_BREATHE_POWER:
1065 case ABIL_BREATHE_STICKY_FLAME:
1066 case ABIL_BREATHE_MEPHITIC:
1067 failure = 30 - you.experience_level;
1069 if (you.form == TRAN_DRAGON)
1073 case ABIL_BREATHE_STEAM:
1074 failure = 20 - you.experience_level;
1076 if (you.form == TRAN_DRAGON)
1081 failure = 42 - (3 * you.experience_level);
1085 failure = 45 - (2 * you.experience_level);
1088 case ABIL_RECHARGING: // this is for deep dwarves {1KB}
1089 failure = 45 - (2 * you.experience_level);
1093 case ABIL_SHAFT_SELF:
1096 // end species abilities (some mutagenic)
1098 // begin demonic powers {dlb}
1100 failure = 50 - you.experience_level;
1102 // end demonic powers {dlb}
1105 failure = 48 - (12 * player_mutation_level(MUT_BLINK))
1106 - you.experience_level / 2;
1109 // begin transformation abilities {dlb}
1110 case ABIL_END_TRANSFORMATION:
1113 // end transformation abilities {dlb}
1115 // begin item abilities - some possibly mutagenic {dlb}
1116 case ABIL_EVOKE_TURN_INVISIBLE:
1117 case ABIL_EVOKE_TELEPORTATION:
1118 failure = 60 - you.skill(SK_EVOCATIONS, 2);
1121 case ABIL_EVOKE_TURN_VISIBLE:
1122 case ABIL_STOP_FLYING:
1126 case ABIL_EVOKE_FLIGHT:
1127 case ABIL_EVOKE_BLINK:
1128 failure = 40 - you.skill(SK_EVOCATIONS, 2);
1130 case ABIL_EVOKE_BERSERK:
1131 case ABIL_EVOKE_FOG:
1132 case ABIL_EVOKE_TELEPORT_CONTROL:
1133 failure = 50 - you.skill(SK_EVOCATIONS, 2);
1135 case ABIL_EVOKE_TWISTER:
1136 failure = 100 - you.skill(SK_EVOCATIONS, 4);
1138 // end item abilities - some possibly mutagenic {dlb}
1140 // begin invocations {dlb}
1141 // Abilities with no fail rate.
1142 case ABIL_ZIN_CURE_ALL_MUTATIONS:
1143 case ABIL_ELYVILON_LIFESAVING:
1144 case ABIL_TROG_BURN_SPELLBOOKS:
1145 case ABIL_ASHENZARI_TRANSFER_KNOWLEDGE:
1146 case ABIL_ASHENZARI_END_TRANSFER:
1147 case ABIL_ASHENZARI_SCRYING:
1148 case ABIL_BEOGH_GIFT_ITEM:
1149 case ABIL_JIYVA_CALL_JELLY:
1150 case ABIL_JIYVA_CURE_BAD_MUTATION:
1151 case ABIL_JIYVA_JELLY_PARALYSE:
1152 case ABIL_GOZAG_POTION_PETITION:
1153 case ABIL_GOZAG_CALL_MERCHANT:
1154 case ABIL_GOZAG_BRIBE_BRANCH:
1155 case ABIL_RU_DRAW_OUT_POWER:
1156 case ABIL_RU_POWER_LEAP:
1157 case ABIL_RU_APOCALYPSE:
1158 case ABIL_RU_SACRIFICE_PURITY:
1159 case ABIL_RU_SACRIFICE_WORDS:
1160 case ABIL_RU_SACRIFICE_DRINK:
1161 case ABIL_RU_SACRIFICE_ESSENCE:
1162 case ABIL_RU_SACRIFICE_HEALTH:
1163 case ABIL_RU_SACRIFICE_STEALTH:
1164 case ABIL_RU_SACRIFICE_ARTIFICE:
1165 case ABIL_RU_SACRIFICE_LOVE:
1166 case ABIL_RU_SACRIFICE_COURAGE:
1167 case ABIL_RU_SACRIFICE_ARCANA:
1168 case ABIL_RU_SACRIFICE_NIMBLENESS:
1169 case ABIL_RU_SACRIFICE_DURABILITY:
1170 case ABIL_RU_SACRIFICE_HAND:
1171 case ABIL_RU_SACRIFICE_EXPERIENCE:
1172 case ABIL_RU_SACRIFICE_SKILL:
1173 case ABIL_RU_REJECT_SACRIFICES:
1174 case ABIL_STOP_RECALL:
1179 case ABIL_YRED_ANIMATE_REMAINS_OR_DEAD: // Placeholder.
1183 // Trog and Jiyva abilities, only based on piety.
1184 case ABIL_TROG_BERSERK: // piety >= 30
1189 case ABIL_TROG_REGEN_MR: // piety >= 50
1191 failure = piety_breakpoint(2) - you.piety; // starts at 25%
1194 case ABIL_TROG_BROTHERS_IN_ARMS: // piety >= 100
1196 failure = piety_breakpoint(5) - you.piety; // starts at 60%
1199 case ABIL_JIYVA_SLIMIFY:
1201 failure = 90 - you.piety / 2;
1204 // Other invocations, based on piety and Invocations skill.
1205 case ABIL_ELYVILON_PURIFICATION:
1207 failure = 20 - (you.piety / 20) - you.skill(SK_INVOCATIONS, 5);
1210 case ABIL_ZIN_RECITE:
1211 case ABIL_BEOGH_RECALL_ORCISH_FOLLOWERS:
1212 case ABIL_OKAWARU_HEROISM:
1213 case ABIL_ELYVILON_LESSER_HEALING:
1214 case ABIL_LUGONU_ABYSS_EXIT:
1215 case ABIL_FEDHAS_SUNLIGHT:
1216 case ABIL_FEDHAS_EVOLUTION:
1217 case ABIL_DITHMENOS_SHADOW_STEP:
1219 failure = 30 - (you.piety / 20) - you.skill(SK_INVOCATIONS, 6);
1222 case ABIL_YRED_ANIMATE_REMAINS:
1223 case ABIL_YRED_ANIMATE_DEAD:
1224 case ABIL_YRED_INJURY_MIRROR:
1225 case ABIL_CHEIBRIADOS_TIME_BEND:
1227 failure = 40 - (you.piety / 20) - you.skill(SK_INVOCATIONS, 4);
1230 case ABIL_ZIN_VITALISATION:
1231 case ABIL_TSO_DIVINE_SHIELD:
1232 case ABIL_BEOGH_SMITING:
1233 case ABIL_SIF_MUNA_FORGET_SPELL:
1234 case ABIL_MAKHLEB_MINOR_DESTRUCTION:
1235 case ABIL_MAKHLEB_LESSER_SERVANT_OF_MAKHLEB:
1236 case ABIL_ELYVILON_GREATER_HEALING:
1237 case ABIL_ELYVILON_HEAL_OTHER:
1238 case ABIL_LUGONU_BEND_SPACE:
1239 case ABIL_FEDHAS_PLANT_RING:
1240 case ABIL_QAZLAL_UPHEAVAL:
1242 failure = 40 - (you.piety / 20) - you.skill(SK_INVOCATIONS, 5);
1245 case ABIL_KIKU_RECEIVE_CORPSES:
1247 failure = 40 - (you.piety / 20) - you.skill(SK_NECROMANCY, 5);
1250 case ABIL_SIF_MUNA_CHANNEL_ENERGY:
1252 failure = 40 - you.intel() - you.skill(SK_INVOCATIONS, 1);
1255 case ABIL_YRED_RECALL_UNDEAD_SLAVES:
1257 failure = 50 - (you.piety / 20) - you.skill(SK_INVOCATIONS, 4);
1260 case ABIL_ZIN_IMPRISON:
1261 case ABIL_LUGONU_BANISH:
1262 case ABIL_CHEIBRIADOS_DISTORTION:
1263 case ABIL_QAZLAL_ELEMENTAL_FORCE:
1265 failure = 60 - (you.piety / 20) - you.skill(SK_INVOCATIONS, 5);
1268 case ABIL_KIKU_TORMENT:
1270 failure = 60 - (you.piety / 20) - you.skill(SK_NECROMANCY, 5);
1273 case ABIL_MAKHLEB_MAJOR_DESTRUCTION:
1274 case ABIL_FEDHAS_SPAWN_SPORES:
1275 case ABIL_YRED_DRAIN_LIFE:
1276 case ABIL_CHEIBRIADOS_SLOUCH:
1277 case ABIL_OKAWARU_FINESSE:
1279 failure = 60 - (you.piety / 25) - you.skill(SK_INVOCATIONS, 4);
1282 case ABIL_TSO_CLEANSING_FLAME:
1283 case ABIL_MAKHLEB_GREATER_SERVANT_OF_MAKHLEB:
1284 case ABIL_LUGONU_CORRUPT:
1285 case ABIL_FEDHAS_RAIN:
1286 case ABIL_QAZLAL_DISASTER_AREA:
1288 failure = 70 - (you.piety / 25) - you.skill(SK_INVOCATIONS, 4);
1291 case ABIL_ZIN_SANCTUARY:
1292 case ABIL_TSO_SUMMON_DIVINE_WARRIOR:
1293 case ABIL_YRED_ENSLAVE_SOUL:
1294 case ABIL_ELYVILON_DIVINE_VIGOUR:
1295 case ABIL_LUGONU_ABYSS_ENTER:
1296 case ABIL_CHEIBRIADOS_TIME_STEP:
1297 case ABIL_DITHMENOS_SHADOW_FORM:
1299 failure = 80 - (you.piety / 25) - you.skill(SK_INVOCATIONS, 4);
1302 case ABIL_NEMELEX_STACK_FIVE:
1304 failure = 80 - (you.piety / 25) - you.skill(SK_EVOCATIONS, 4);
1307 case ABIL_NEMELEX_DEAL_FOUR:
1309 failure = 70 - (you.piety * 2 / 45) - you.skill(SK_EVOCATIONS, 9) / 2;
1312 case ABIL_NEMELEX_TRIPLE_DRAW:
1314 failure = 60 - (you.piety / 20) - you.skill(SK_EVOCATIONS, 5);
1317 case ABIL_RENOUNCE_RELIGION:
1318 case ABIL_CONVERT_TO_BEOGH:
1323 // end invocations {dlb}
1335 result.fail = failure;
1336 result.is_invocation = invoc;
1337 result.is_zotdef = abil.flags & ABFLAG_ZOTDEF;
1342 const char* ability_name(ability_type ability)
1344 return get_ability_def(ability).name;
1347 vector<const char*> get_ability_names()
1349 vector<const char*> result;
1350 for (const talent &tal : your_talents(false))
1351 result.push_back(ability_name(tal.which));
1355 // XXX: should this be in describe.cc?
1356 string get_ability_desc(const ability_type ability)
1358 const string& name = ability_name(ability);
1360 string lookup = getLongDescription(name + " ability");
1362 if (lookup.empty()) // Nothing found?
1363 lookup = "No description found.\n";
1365 if (god_hates_ability(ability, you.religion))
1367 lookup += uppercase_first(god_name(you.religion))
1368 + " frowns upon the use of this ability.\n";
1372 res << name << "\n\n" << lookup << "\n"
1373 << _detailed_cost_description(ability);
1375 const string quote = getQuoteString(name + " ability");
1377 res << "\n\n" << quote;
1382 static void _print_talent_description(const talent& tal)
1386 print_description(get_ability_desc(tal.which));
1392 void no_ability_msg()
1394 // Give messages if the character cannot use innate talents right now.
1395 // * Vampires can't turn into bats when full of blood.
1396 // * Tengu can't start to fly if already flying.
1397 if (you.species == SP_VAMPIRE && you.experience_level >= 3)
1399 ASSERT(you.hunger_state > HS_SATIATED);
1400 mpr("Sorry, you're too full to transform right now.");
1402 else if (player_mutation_level(MUT_TENGU_FLIGHT)
1403 || player_mutation_level(MUT_BIG_WINGS))
1406 mpr("You're already flying!");
1409 mpr("Sorry, you're not good enough to have a special ability.");
1412 bool activate_ability()
1416 canned_msg(MSG_TOO_BERSERK);
1417 crawl_state.zero_turns_taken();
1421 vector<talent> talents = your_talents(false);
1422 if (talents.empty())
1425 crawl_state.zero_turns_taken();
1431 talents = your_talents(true);
1432 if (talents.empty())
1434 canned_msg(MSG_TOO_CONFUSED);
1435 crawl_state.zero_turns_taken();
1440 int selected = choose_ability_menu(talents);
1444 crawl_state.zero_turns_taken();
1449 while (selected < 0)
1451 msg::streams(MSGCH_PROMPT) << "Use which ability? (? or * to list) "
1454 const int keyin = get_ch();
1456 if (keyin == '?' || keyin == '*')
1458 selected = choose_ability_menu(talents);
1462 crawl_state.zero_turns_taken();
1466 else if (key_is_escape(keyin) || keyin == ' ' || keyin == '\r'
1470 crawl_state.zero_turns_taken();
1473 else if (isaalpha(keyin))
1475 // Try to find the hotkey.
1476 for (unsigned int i = 0; i < talents.size(); ++i)
1478 if (talents[i].hotkey == keyin)
1480 selected = static_cast<int>(i);
1485 // If we can't, cancel out.
1488 mpr("You can't do that.");
1489 crawl_state.zero_turns_taken();
1495 return activate_talent(talents[selected]);
1498 // Check prerequisites for a number of abilities.
1499 // Abort any attempt if these cannot be met, without losing the turn.
1500 // TODO: Many more cases need to be added!
1501 static bool _check_ability_possible(const ability_def& abil,
1502 bool hungerCheck = true,
1508 canned_msg(MSG_TOO_BERSERK);
1512 if (you.confused() && !testbits(abil.flags, ABFLAG_CONF_OK))
1515 canned_msg(MSG_TOO_CONFUSED);
1519 if (silenced(you.pos()))
1521 talent tal = get_talent(abil.ability, false);
1522 if (tal.is_invocation)
1526 mprf("You cannot call out to %s while silenced.",
1527 god_name(you.religion).c_str());
1532 // Don't insta-starve the player.
1533 // (Losing consciousness possible from 400 downward.)
1534 if (hungerCheck && !you.undead_state())
1536 const int expected_hunger = you.hunger - abil.food_cost * 2;
1539 dprf("hunger: %d, max. food_cost: %d, expected hunger: %d",
1540 you.hunger, abil.food_cost * 2, expected_hunger);
1542 // Safety margin for natural hunger, mutations etc.
1543 if (expected_hunger <= 50)
1546 canned_msg(MSG_TOO_HUNGRY);
1551 // in case of mp rot ability, check is the player have enough natural MP
1552 // (avoid use of ring/staf of magical power)
1553 if ((abil.flags & ABFLAG_PERMANENT_MP)
1554 && get_real_mp(false) < (int)abil.mp_cost)
1557 mpr("You don't have enough innate magic capacity to sacrifice.");
1561 switch (abil.ability)
1563 case ABIL_ZIN_RECITE:
1565 if (!zin_check_able_to_recite(quiet))
1568 if (zin_check_recite_to_monsters(quiet) != 1)
1571 mpr("There's no appreciative audience!");
1577 case ABIL_ZIN_CURE_ALL_MUTATIONS:
1578 return how_mutated();
1580 case ABIL_ZIN_SANCTUARY:
1581 if (env.sanctuary_time)
1584 mpr("There's already a sanctuary in place on this level.");
1589 case ABIL_ELYVILON_PURIFICATION:
1590 if (!you.disease && !you.duration[DUR_POISONING]
1591 && !you.duration[DUR_CONF] && !you.duration[DUR_SLOW]
1592 && !you.petrifying()
1593 && you.strength(false) == you.max_strength()
1594 && you.intel(false) == you.max_intel()
1595 && you.dex(false) == you.max_dex()
1597 && !you.duration[DUR_WEAK])
1600 mpr("Nothing ails you!");
1605 case ABIL_MUMMY_RESTORATION:
1606 if (you.strength(false) == you.max_strength()
1607 && you.intel(false) == you.max_intel()
1608 && you.dex(false) == you.max_dex()
1609 && !player_rotted())
1612 mpr("You don't need to restore your stats or health!");
1617 case ABIL_LUGONU_ABYSS_EXIT:
1618 if (!player_in_branch(BRANCH_ABYSS))
1621 mpr("You aren't in the Abyss!");
1626 case ABIL_LUGONU_CORRUPT:
1627 return !is_level_incorruptible(quiet);
1629 case ABIL_LUGONU_ABYSS_ENTER:
1630 if (player_in_branch(BRANCH_ABYSS) || brdepth[BRANCH_ABYSS] == -1)
1633 mpr("You're already here!");
1638 case ABIL_SIF_MUNA_FORGET_SPELL:
1639 if (you.spell_no == 0)
1642 canned_msg(MSG_NO_SPELLS);
1647 case ABIL_ASHENZARI_TRANSFER_KNOWLEDGE:
1648 if (all_skills_maxed(true))
1651 mpr("You have nothing more to learn.");
1656 case ABIL_OKAWARU_FINESSE:
1657 if (stasis_blocks_effect(false,
1659 : "%s makes your neck tingle."))
1665 case ABIL_FEDHAS_EVOLUTION:
1666 return fedhas_check_evolve_flora(quiet);
1668 case ABIL_FEDHAS_SPAWN_SPORES:
1670 const int retval = fedhas_check_corpse_spores(quiet);
1676 mpr("No corpses are in range.");
1685 case ABIL_SPIT_POISON:
1686 case ABIL_BREATHE_FIRE:
1687 case ABIL_BREATHE_FROST:
1688 case ABIL_BREATHE_POISON:
1689 case ABIL_BREATHE_LIGHTNING:
1690 case ABIL_SPIT_ACID:
1691 case ABIL_BREATHE_POWER:
1692 case ABIL_BREATHE_STICKY_FLAME:
1693 case ABIL_BREATHE_STEAM:
1694 case ABIL_BREATHE_MEPHITIC:
1695 if (you.duration[DUR_BREATH_WEAPON])
1698 canned_msg(MSG_CANNOT_DO_YET);
1704 case ABIL_EVOKE_BLINK:
1706 const string no_tele_reason = you.no_tele_reason(false, true);
1707 if (no_tele_reason.empty())
1711 mpr(no_tele_reason);
1715 case ABIL_EVOKE_BERSERK:
1716 case ABIL_TROG_BERSERK:
1717 return you.can_go_berserk(true, false, true)
1718 && (quiet || berserk_check_wielded_weapon());
1720 case ABIL_EVOKE_FOG:
1721 if (env.cgrid(you.pos()) != EMPTY_CLOUD)
1724 mpr("It's too cloudy to do that here.");
1729 case ABIL_GOZAG_POTION_PETITION:
1730 return gozag_setup_potion_petition(quiet);
1732 case ABIL_GOZAG_CALL_MERCHANT:
1733 return gozag_setup_call_merchant(quiet);
1735 case ABIL_GOZAG_BRIBE_BRANCH:
1736 return gozag_check_bribe_branch(quiet);
1738 case ABIL_RU_SACRIFICE_EXPERIENCE:
1739 if (you.experience_level <= RU_SAC_XP_LEVELS)
1742 mpr("You don't have enough experience to sacrifice.");
1752 bool check_ability_possible(const ability_type ability, bool hungerCheck,
1755 return _check_ability_possible(get_ability_def(ability), hungerCheck,
1759 bool activate_talent(const talent& tal)
1763 canned_msg(MSG_TOO_BERSERK);
1764 crawl_state.zero_turns_taken();
1768 // Doing these would outright kill the player.
1769 // (or, in the case of the stat-zeros, they'd at least be extremely
1771 if (tal.which == ABIL_STOP_FLYING)
1773 if (is_feat_dangerous(grd(you.pos()), false, true))
1775 mpr("Stopping flight right now would be fatal!");
1776 crawl_state.zero_turns_taken();
1780 else if (tal.which == ABIL_TRAN_BAT)
1782 if (!check_form_stat_safety(TRAN_BAT))
1784 crawl_state.zero_turns_taken();
1788 else if (tal.which == ABIL_END_TRANSFORMATION)
1790 if (feat_dangerous_for_form(TRAN_NONE, env.grid(you.pos())))
1792 mprf("Turning back right now would cause you to %s!",
1793 env.grid(you.pos()) == DNGN_LAVA ? "burn" : "drown");
1795 crawl_state.zero_turns_taken();
1799 if (!check_form_stat_safety(TRAN_NONE))
1801 crawl_state.zero_turns_taken();
1806 if ((tal.which == ABIL_EVOKE_BERSERK || tal.which == ABIL_TROG_BERSERK)
1807 && !you.can_go_berserk(true))
1809 crawl_state.zero_turns_taken();
1813 if ((tal.which == ABIL_EVOKE_FLIGHT || tal.which == ABIL_TRAN_BAT || tal.which == ABIL_FLY)
1814 && !flight_allowed())
1816 crawl_state.zero_turns_taken();
1820 // Some abilities don't need a hunger check.
1821 bool hungerCheck = true;
1824 case ABIL_RENOUNCE_RELIGION:
1825 case ABIL_CONVERT_TO_BEOGH:
1826 case ABIL_STOP_FLYING:
1827 case ABIL_EVOKE_TURN_VISIBLE:
1828 case ABIL_END_TRANSFORMATION:
1829 case ABIL_DELAYED_FIREBALL:
1830 case ABIL_STOP_SINGING:
1831 case ABIL_MUMMY_RESTORATION:
1833 case ABIL_ASHENZARI_END_TRANSFER:
1834 case ABIL_ZIN_VITALISATION:
1835 case ABIL_GOZAG_POTION_PETITION:
1836 hungerCheck = false;
1842 if (hungerCheck && !you.undead_state() && !you_foodless()
1843 && you.hunger_state == HS_STARVING)
1845 canned_msg(MSG_TOO_HUNGRY);
1846 crawl_state.zero_turns_taken();
1850 const ability_def& abil = get_ability_def(tal.which);
1852 // Check that we can afford to pay the costs.
1853 // Note that mutation shenanigans might leave us with negative MP,
1854 // so don't fail in that case if there's no MP cost.
1855 if (abil.mp_cost > 0 && !enough_mp(abil.mp_cost, false, true))
1857 crawl_state.zero_turns_taken();
1861 const int hpcost = abil.hp_cost.cost(you.hp_max);
1862 if (hpcost > 0 && !enough_hp(hpcost, false))
1864 crawl_state.zero_turns_taken();
1868 const int zpcost = _zp_cost(abil);
1871 if (!enough_zp(zpcost, false))
1873 crawl_state.zero_turns_taken();
1878 if (!_check_ability_possible(abil, hungerCheck))
1880 crawl_state.zero_turns_taken();
1884 bool fail = random2avg(100, 3) < tal.fail;
1886 const spret_type ability_result = _do_ability(abil, fail);
1887 switch (ability_result)
1891 practise(EX_USED_ABIL, abil.ability);
1892 _pay_ability_costs(abil, zpcost);
1893 count_action(tal.is_invocation ? CACT_INVOKE : CACT_ABIL, abil.ability);
1896 mpr("You fail to use your ability.");
1897 you.turn_is_over = true;
1900 crawl_state.zero_turns_taken();
1904 die("Weird ability return type");
1909 static int _calc_breath_ability_range(ability_type ability)
1911 // Following monster draconian abilities.
1914 case ABIL_BREATHE_FIRE: return 6;
1915 case ABIL_BREATHE_FROST: return 6;
1916 case ABIL_BREATHE_MEPHITIC: return 7;
1917 case ABIL_BREATHE_LIGHTNING: return 8;
1918 case ABIL_SPIT_ACID: return 8;
1919 case ABIL_BREATHE_POWER: return 8;
1920 case ABIL_BREATHE_STICKY_FLAME: return 1;
1921 case ABIL_BREATHE_STEAM: return 7;
1922 case ABIL_BREATHE_POISON: return 7;
1924 die("Bad breath type!");
1930 static bool _sticky_flame_can_hit(const actor *act)
1932 if (act->is_monster())
1934 const monster* mons = act->as_monster();
1936 testbeam.thrower = KILL_YOU;
1937 zappy(ZAP_BREATHE_STICKY_FLAME, 100, testbeam);
1939 return !testbeam.ignores_monster(mons);
1948 * @param abil The actual ability used.
1949 * @param fail If true, the ability is doomed to fail, and SPRET_FAIL will
1950 * be returned if the ability is not SPRET_ABORTed.
1951 * @returns Whether the spell succeeded (SPRET_SUCCESS), failed (SPRET_FAIL),
1952 * or was canceled (SPRET_ABORT). Never returns SPRET_NONE.
1954 static spret_type _do_ability(const ability_def& abil, bool fail)
1961 direction_chooser_args args;
1962 args.restricts = DIR_TARGET;
1963 args.needs_path = false;
1964 args.may_target_monster = false;
1966 // Note: the costs will not be applied until after this switch
1967 // statement... it's assumed that only failures have returned! - bwr
1968 switch (abil.ability)
1970 case ABIL_MAKE_FUNGUS:
1972 if (count_allies() > MAX_MONSTERS / 2)
1974 mpr("Mushrooms don't grow well in such thickets.");
1977 args.top_prompt="Center fungus circle where?";
1978 direction(abild, args);
1985 for (adjacent_iterator ai(abild.target); ai; ++ai)
1987 place_monster(mgen_data(MONS_FUNGUS, BEH_FRIENDLY, &you, 0, 0, *ai,
1988 you.pet_target), true);
1992 // Begin ZotDef allies
1993 case ABIL_MAKE_PLANT:
1994 case ABIL_MAKE_OKLOB_SAPLING:
1995 case ABIL_MAKE_OKLOB_PLANT:
1996 case ABIL_MAKE_BURNING_BUSH:
1997 case ABIL_MAKE_ICE_STATUE:
1999 case ABIL_MAKE_OBSIDIAN_STATUE:
2000 case ABIL_MAKE_CURSE_SKULL:
2001 case ABIL_MAKE_LIGHTNING_SPIRE:
2003 if (!create_zotdef_ally(_monster_for_ability(abil),
2004 _zd_mons_description_for_ability(abil).c_str()))
2009 // End ZotDef Allies
2011 case ABIL_MAKE_TELEPORT:
2013 you_teleport_now(true);
2017 case ABIL_MAKE_ARROW_TRAP:
2018 case ABIL_MAKE_BOLT_TRAP:
2019 case ABIL_MAKE_SPEAR_TRAP:
2020 case ABIL_MAKE_NEEDLE_TRAP:
2021 case ABIL_MAKE_NET_TRAP:
2022 case ABIL_MAKE_ALARM_TRAP:
2023 case ABIL_MAKE_BLADE_TRAP:
2025 if (!create_trap(_trap_for_ability(abil)))
2030 case ABIL_MAKE_OKLOB_CIRCLE:
2032 args.top_prompt = "Center oklob circle where?";
2033 direction(abild, args);
2040 for (adjacent_iterator ai(abild.target); ai; ++ai)
2042 place_monster(mgen_data(MONS_OKLOB_PLANT, BEH_FRIENDLY, &you, 0, 0,
2043 *ai, you.pet_target), true);
2047 case ABIL_MAKE_ACQUIRE_GOLD:
2049 acquirement(OBJ_GOLD, AQ_SCROLL);
2052 case ABIL_MAKE_ACQUIREMENT:
2054 acquirement(OBJ_RANDOM, AQ_SCROLL);
2057 case ABIL_MAKE_WATER:
2059 zotdef_create_pond(you.pos(), 3);
2062 case ABIL_MAKE_BAZAAR:
2065 // Early exit: don't clobber important features.
2066 if (feat_is_critical(grd(you.pos())))
2068 mpr("The dungeon trembles momentarily.");
2072 // Generate a portal to something.
2073 const map_def *mapidx = random_map_for_tag("zotdef_bazaar", false);
2074 if (mapidx && dgn_safe_place_map(mapidx, false, true, you.pos()))
2075 mpr("A mystic portal forms.");
2078 mpr("A buggy portal flickers into view, then vanishes.");
2085 case ABIL_MAKE_ALTAR:
2087 if (!zotdef_create_altar())
2089 mpr("The dungeon dims for a moment.");
2094 case ABIL_MAKE_GRENADES:
2097 mgen_data(MONS_GIANT_SPORE, BEH_FRIENDLY, &you, 6, 0,
2098 you.pos(), you.pet_target,
2101 mpr("You create a living grenade.");
2104 mgen_data(MONS_GIANT_SPORE, BEH_FRIENDLY, &you, 6, 0,
2105 you.pos(), you.pet_target,
2108 mpr("You create a living grenade.");
2112 case ABIL_REMOVE_CURSE:
2115 lose_stat(STAT_RANDOM, 1, true);
2118 case ABIL_MUMMY_RESTORATION:
2121 mpr("You infuse your body with magical energy.");
2122 bool did_restore = restore_stat(STAT_ALL, 0, false);
2124 const int oldhpmax = you.hp_max;
2126 if (you.hp_max > oldhpmax)
2129 // If nothing happened, don't take one max MP, don't use a turn.
2132 canned_msg(MSG_NOTHING_HAPPENS);
2139 case ABIL_RECHARGING:
2141 if (recharge_wand() <= 0)
2142 return SPRET_ABORT; // fail message is already given
2150 mpr("You extend your mandibles.");
2154 mpr("You are already prepared to dig.");
2159 case ABIL_SHAFT_SELF:
2161 if (you.can_do_shaft_ability(false))
2163 if (yesno("Are you sure you want to shaft yourself?", true, 'n'))
2164 start_delay(DELAY_SHAFT_SELF, 1);
2172 case ABIL_DELAYED_FIREBALL:
2175 // Note: Power level of ball calculated at release. - bwr
2176 power = calc_spell_power(SPELL_DELAYED_FIREBALL, true);
2177 beam.range = spell_range(SPELL_FIREBALL, power);
2179 targetter_beam tgt(&you, beam.range, ZAP_FIREBALL, power, 1, 1);
2181 if (!spell_direction(spd, beam, DIR_NONE, TARG_HOSTILE, beam.range,
2182 true, true, false, nullptr,
2183 "Aiming: <white>Delayed Fireball</white>",
2189 if (!zapping(ZAP_FIREBALL, power, beam, true, nullptr, false))
2192 // Only one allowed, since this is instantaneous. - bwr
2193 you.attribute[ATTR_DELAYED_FIREBALL] = 0;
2197 case ABIL_SPIT_POISON: // Spit poison mutation
2198 power = you.experience_level
2199 + player_mutation_level(MUT_SPIT_POISON) * 5;
2200 beam.range = 6; // following Venom Bolt
2202 if (!spell_direction(abild, beam)
2203 || !player_tracer(ZAP_SPIT_POISON, power, beam))
2210 zapping(ZAP_SPIT_POISON, power, beam);
2211 zin_recite_interrupt();
2212 you.set_duration(DUR_BREATH_WEAPON, 3 + random2(5));
2216 case ABIL_EVOKE_TELEPORTATION: // ring of teleportation
2221 case ABIL_BREATHE_STICKY_FLAME:
2223 targetter_splash hitfunc(&you);
2225 if (!spell_direction(abild, beam,
2226 DIR_NONE, TARG_HOSTILE, 0, true, true, false,
2227 nullptr, nullptr, false,
2233 if (stop_attack_prompt(hitfunc, "spit at", _sticky_flame_can_hit))
2237 zapping(ZAP_BREATHE_STICKY_FLAME, (you.form == TRAN_DRAGON) ?
2238 2 * you.experience_level : you.experience_level,
2239 beam, false, "You spit a glob of burning liquid.");
2241 zin_recite_interrupt();
2242 you.increase_duration(DUR_BREATH_WEAPON,
2243 3 + random2(10) + random2(30 - you.experience_level));
2247 case ABIL_BREATHE_FIRE:
2248 case ABIL_BREATHE_FROST:
2249 case ABIL_BREATHE_POISON:
2250 case ABIL_SPIT_ACID:
2251 case ABIL_BREATHE_POWER:
2252 case ABIL_BREATHE_STEAM:
2253 case ABIL_BREATHE_MEPHITIC:
2254 beam.range = _calc_breath_ability_range(abil.ability);
2255 if (!spell_direction(abild, beam))
2258 // fallthrough to ABIL_BREATHE_LIGHTNING
2260 case ABIL_BREATHE_LIGHTNING: // not targeted
2263 // TODO: refactor this to use only one call to zapping(), don't
2264 // duplicate its fail_check(), split out breathe_lightning, etc
2266 switch (abil.ability)
2268 case ABIL_BREATHE_FIRE:
2270 power = you.experience_level
2271 + player_mutation_level(MUT_BREATHE_FLAMES) * 4;
2273 if (you.form == TRAN_DRAGON)
2276 string msg = "You breathe a blast of fire";
2277 msg += (power < 15) ? '.' : '!';
2279 if (!zapping(ZAP_BREATHE_FIRE, power, beam, true, msg.c_str()))
2284 case ABIL_BREATHE_FROST:
2285 if (!zapping(ZAP_BREATHE_FROST,
2286 (you.form == TRAN_DRAGON) ?
2287 2 * you.experience_level : you.experience_level,
2289 "You exhale a wave of freezing cold."))
2295 case ABIL_BREATHE_POISON:
2296 if (!zapping(ZAP_BREATHE_POISON, you.experience_level, beam, true,
2297 "You exhale a blast of poison gas."))
2303 case ABIL_BREATHE_LIGHTNING:
2304 mpr("You breathe a wild blast of lightning!");
2305 black_drac_breath();
2308 case ABIL_SPIT_ACID:
2309 if (!zapping(ZAP_BREATHE_ACID,
2310 (you.form == TRAN_DRAGON) ?
2311 2 * you.experience_level : you.experience_level,
2312 beam, true, "You spit a glob of acid."))
2318 case ABIL_BREATHE_POWER:
2319 if (!zapping(ZAP_BREATHE_POWER,
2320 (you.form == TRAN_DRAGON) ?
2321 2 * you.experience_level : you.experience_level,
2323 "You spit a bolt of dispelling energy."))
2329 case ABIL_BREATHE_STICKY_FLAME:
2330 if (!zapping(ZAP_BREATHE_STICKY_FLAME,
2331 (you.form == TRAN_DRAGON) ?
2332 2 * you.experience_level : you.experience_level,
2334 "You spit a glob of burning liquid."))
2340 case ABIL_BREATHE_STEAM:
2341 if (!zapping(ZAP_BREATHE_STEAM,
2342 (you.form == TRAN_DRAGON) ?
2343 2 * you.experience_level : you.experience_level,
2345 "You exhale a blast of scalding steam."))
2351 case ABIL_BREATHE_MEPHITIC:
2352 if (!zapping(ZAP_BREATHE_MEPHITIC,
2353 (you.form == TRAN_DRAGON) ?
2354 2 * you.experience_level : you.experience_level,
2356 "You exhale a blast of noxious fumes."))
2366 zin_recite_interrupt();
2367 you.increase_duration(DUR_BREATH_WEAPON,
2368 3 + random2(10) + random2(30 - you.experience_level));
2370 if (abil.ability == ABIL_BREATHE_STEAM
2371 || abil.ability == ABIL_SPIT_ACID)
2373 you.duration[DUR_BREATH_WEAPON] /= 2;
2378 case ABIL_EVOKE_BLINK: // randarts
2379 case ABIL_BLINK: // mutation
2380 return cast_blink(true, fail);
2383 case ABIL_EVOKE_BERSERK: // amulet of rage, randarts
2385 you.go_berserk(true);
2388 // Fly (tengu/drac) - permanent at high XL
2391 if (you.racial_permanent_flight())
2393 you.attribute[ATTR_PERM_FLIGHT] = 1;
2395 if (you.species == SP_TENGU)
2396 mpr("You feel very comfortable in the air.");
2399 cast_fly(you.experience_level * 4);
2405 if (your_spells(SPELL_HELLFIRE,
2406 you.experience_level * 10, false) == SPRET_ABORT)
2412 case ABIL_EVOKE_TURN_INVISIBLE: // ring, cloaks, randarts
2414 potionlike_effect(POT_INVISIBILITY, you.skill(SK_EVOCATIONS, 2) + 5);
2415 contaminate_player(1000 + random2(2000), true);
2418 case ABIL_EVOKE_TURN_VISIBLE:
2420 ASSERT(!you.attribute[ATTR_INVIS_UNCANCELLABLE]);
2421 mpr("You feel less transparent.");
2422 you.duration[DUR_INVIS] = 1;
2425 case ABIL_EVOKE_FLIGHT: // ring, boots, randarts
2427 ASSERT(!get_form()->forbids_flight());
2428 if (you.wearing_ego(EQ_ALL_ARMOUR, SPARM_FLYING))
2430 bool standing = !you.airborne();
2431 you.attribute[ATTR_PERM_FLIGHT] = 1;
2435 mpr("You feel more buoyant.");
2438 fly_player(you.skill(SK_EVOCATIONS, 2) + 30);
2440 case ABIL_EVOKE_FOG: // cloak of the Thief
2442 mpr("With a swish of your cloak, you release a cloud of fog.");
2443 big_cloud(random_smoke_type(), &you, you.pos(), 50, 8 + random2(8));
2446 case ABIL_EVOKE_TELEPORT_CONTROL:
2448 cast_teleport_control(30 + you.skill(SK_EVOCATIONS, 2), false);
2451 case ABIL_EVOKE_TWISTER:
2456 case ABIL_STOP_SINGING:
2458 you.duration[DUR_SONG_OF_SLAYING] = 0;
2459 mpr("You stop singing.");
2462 case ABIL_STOP_FLYING:
2464 you.duration[DUR_FLIGHT] = 0;
2465 you.attribute[ATTR_PERM_FLIGHT] = 0;
2469 case ABIL_END_TRANSFORMATION:
2471 you.time_taken = div_rand_round(you.time_taken * 3, 2);
2476 case ABIL_ZIN_RECITE:
2479 if (zin_check_recite_to_monsters() == 1)
2481 you.attribute[ATTR_RECITE_TYPE] = (recite_type) random2(NUM_RECITE_TYPES); // This is just flavor
2482 you.attribute[ATTR_RECITE_SEED] = random2(2187); // 3^7
2483 you.attribute[ATTR_RECITE_HP] = you.hp;
2484 you.duration[DUR_RECITE] = 3 * BASELINE_DELAY;
2485 mprf("You clear your throat and prepare to recite.");
2494 case ABIL_ZIN_VITALISATION:
2496 zin_recite_interrupt();
2500 case ABIL_ZIN_IMPRISON:
2502 beam.range = LOS_RADIUS;
2503 if (!spell_direction(spd, beam, DIR_TARGET, TARG_HOSTILE, 0, false))
2506 if (beam.target == you.pos())
2508 mpr("You cannot imprison yourself!");
2512 monster* mons = monster_at(beam.target);
2514 if (mons == nullptr || !you.can_see(mons))
2516 mpr("There is no monster there to imprison!");
2520 if (mons_is_firewood(mons) || mons_is_conjured(mons->type))
2522 mpr("You cannot imprison that!");
2526 if (mons->friendly() || mons->good_neutral())
2528 mpr("You cannot imprison a law-abiding creature!");
2534 zin_recite_interrupt();
2535 power = 3 + (roll_dice(5, you.skill(SK_INVOCATIONS, 5) + 12) / 26);
2537 if (!cast_imprison(power, mons, -GOD_ZIN))
2542 case ABIL_ZIN_SANCTUARY:
2544 zin_recite_interrupt();
2545 if (!zin_sanctuary())
2549 case ABIL_ZIN_CURE_ALL_MUTATIONS:
2551 zin_recite_interrupt();
2552 zin_remove_all_mutations();
2555 case ABIL_TSO_DIVINE_SHIELD:
2557 tso_divine_shield();
2560 case ABIL_TSO_CLEANSING_FLAME:
2562 cleansing_flame(10 + you.skill_rdiv(SK_INVOCATIONS, 7, 6),
2563 CLEANSING_FLAME_INVOCATION, you.pos(), &you);
2566 case ABIL_TSO_SUMMON_DIVINE_WARRIOR:
2568 summon_holy_warrior(you.skill(SK_INVOCATIONS, 4), false);
2571 case ABIL_KIKU_RECEIVE_CORPSES:
2573 kiku_receive_corpses(you.skill(SK_NECROMANCY, 4));
2576 case ABIL_KIKU_TORMENT:
2578 if (!kiku_take_corpse())
2580 mpr("There are no corpses to sacrifice!");
2583 simple_god_message(" torments the living!");
2584 torment(&you, TORMENT_KIKUBAAQUDGHA, you.pos());
2587 case ABIL_YRED_INJURY_MIRROR:
2589 if (yred_injury_mirror())
2590 mpr("Another wave of unholy energy enters you.");
2593 mprf("You offer yourself to %s, and fill with unholy energy.",
2594 god_name(you.religion).c_str());
2596 you.duration[DUR_MIRROR_DAMAGE] = 9 * BASELINE_DELAY
2597 + random2avg(you.piety * BASELINE_DELAY, 2) / 10;
2600 case ABIL_YRED_ANIMATE_REMAINS:
2601 case ABIL_YRED_ANIMATE_DEAD:
2603 if (!yred_animate_remains_or_dead())
2607 case ABIL_YRED_RECALL_UNDEAD_SLAVES:
2609 start_recall(RECALL_YRED);
2612 case ABIL_YRED_DRAIN_LIFE:
2614 cast_los_attack_spell(SPELL_DRAIN_LIFE, you.skill_rdiv(SK_INVOCATIONS),
2618 case ABIL_YRED_ENSLAVE_SOUL:
2621 power = you.skill(SK_INVOCATIONS, 4);
2622 beam.range = LOS_RADIUS;
2624 if (!spell_direction(spd, beam))
2627 if (beam.target == you.pos())
2629 mpr("Your soul already belongs to Yredelemnul.");
2633 monster* mons = monster_at(beam.target);
2634 if (mons == nullptr || !you.can_see(mons)
2635 || !ench_flavour_affects_monster(BEAM_ENSLAVE_SOUL, mons))
2637 mpr("You see nothing there you can enslave the soul of!");
2641 // The monster can be no more than lightly wounded/damaged.
2642 if (mons_get_damage_level(mons) > MDAM_LIGHTLY_DAMAGED)
2644 simple_monster_message(mons, "'s soul is too badly injured.");
2649 return zapping(ZAP_ENSLAVE_SOUL, power, beam, false, nullptr, fail);
2652 case ABIL_SIF_MUNA_CHANNEL_ENERGY:
2654 mpr("You channel some magical energy.");
2656 inc_mp(1 + random2(you.skill_rdiv(SK_INVOCATIONS, 1, 4) + 2));
2659 case ABIL_OKAWARU_HEROISM:
2661 mprf(MSGCH_DURATION, you.duration[DUR_HEROISM]
2662 ? "You feel more confident with your borrowed prowess."
2663 : "You gain the combat prowess of a mighty hero.");
2665 you.increase_duration(DUR_HEROISM,
2666 35 + random2(you.skill(SK_INVOCATIONS, 8)), 80);
2667 you.redraw_evasion = true;
2668 you.redraw_armour_class = true;
2671 case ABIL_OKAWARU_FINESSE:
2673 if (stasis_blocks_effect(true, "%s emits a piercing whistle.",
2674 20, "%s makes your neck tingle."))
2676 // Identify the amulet and spend costs - finesse will be aborted
2677 // for free with an identified amulet.
2681 if (you.duration[DUR_FINESSE])
2683 // "Your [hand(s)] get{s} new energy."
2684 mprf(MSGCH_DURATION, "%s",
2685 you.hands_act("get", "new energy.").c_str());
2688 mprf(MSGCH_DURATION, "You can now deal lightning-fast blows.");
2690 you.increase_duration(DUR_FINESSE,
2691 40 + random2(you.skill(SK_INVOCATIONS, 8)), 80);
2693 did_god_conduct(DID_HASTY, 8); // Currently irrelevant.
2696 case ABIL_MAKHLEB_MINOR_DESTRUCTION:
2699 if (!spell_direction(spd, beam))
2702 power = you.skill(SK_INVOCATIONS, 1)
2703 + random2(1 + you.skill(SK_INVOCATIONS, 1))
2704 + random2(1 + you.skill(SK_INVOCATIONS, 1));
2706 // Since the actual beam is random, check with BEAM_MMISSILE and the
2707 // highest range possible.
2708 if (!player_tracer(ZAP_DEBUGGING_RAY, power, beam, 8))
2715 case 0: zapping(ZAP_THROW_FLAME, power, beam); break;
2716 case 1: zapping(ZAP_PAIN, power, beam); break;
2717 case 2: zapping(ZAP_STONE_ARROW, power, beam); break;
2718 case 3: zapping(ZAP_SHOCK, power, beam); break;
2719 case 4: zapping(ZAP_BREATHE_ACID, power/2, beam); break;
2723 case ABIL_MAKHLEB_LESSER_SERVANT_OF_MAKHLEB:
2725 summon_demon_type(random_choose(MONS_HELLWING, MONS_NEQOXEC,
2726 MONS_ORANGE_DEMON, MONS_SMOKE_DEMON, MONS_YNOXINUL),
2727 20 + you.skill(SK_INVOCATIONS, 3), GOD_MAKHLEB);
2730 case ABIL_MAKHLEB_MAJOR_DESTRUCTION:
2733 if (!spell_direction(spd, beam))
2736 power = you.skill(SK_INVOCATIONS, 3)
2737 + random2(1 + you.skill(SK_INVOCATIONS, 1))
2738 + random2(1 + you.skill(SK_INVOCATIONS, 1));
2740 // Since the actual beam is random, check with BEAM_MMISSILE and the
2741 // highest range possible.
2742 if (!player_tracer(ZAP_DEBUGGING_RAY, power, beam, 8))
2749 random_choose(ZAP_BOLT_OF_FIRE,
2754 ZAP_BOLT_OF_DRAINING,
2755 ZAP_ORB_OF_ELECTRICITY);
2756 zapping(ztype, power, beam);
2760 case ABIL_MAKHLEB_GREATER_SERVANT_OF_MAKHLEB:
2762 summon_demon_type(random_choose(MONS_EXECUTIONER, MONS_GREEN_DEATH,
2763 MONS_BLIZZARD_DEMON, MONS_BALRUG, MONS_CACODEMON),
2764 20 + you.skill(SK_INVOCATIONS, 3), GOD_MAKHLEB);
2767 case ABIL_TROG_BURN_SPELLBOOKS:
2769 if (!trog_burn_spellbooks())
2773 case ABIL_TROG_BERSERK:
2775 // Trog abilities don't use or train invocations.
2776 you.go_berserk(true);
2779 case ABIL_TROG_REGEN_MR:
2781 // Trog abilities don't use or train invocations.
2782 trog_do_trogs_hand(you.piety / 2);
2785 case ABIL_TROG_BROTHERS_IN_ARMS:
2787 // Trog abilities don't use or train invocations.
2788 summon_berserker(you.piety +
2789 random2(you.piety/4) - random2(you.piety/4),
2793 case ABIL_SIF_MUNA_FORGET_SPELL:
2795 if (cast_selective_amnesia() <= 0)
2799 case ABIL_ELYVILON_LIFESAVING:
2801 if (you.duration[DUR_LIFESAVING])
2802 mpr("You renew your call for help.");
2805 mprf("You beseech %s to protect your life.",
2806 god_name(you.religion).c_str());
2808 // Might be a decrease, this is intentional (like Yred).
2809 you.duration[DUR_LIFESAVING] = 9 * BASELINE_DELAY
2810 + random2avg(you.piety * BASELINE_DELAY, 2) / 10;
2813 case ABIL_ELYVILON_LESSER_HEALING:
2816 int pow = 3 + (you.skill_rdiv(SK_INVOCATIONS, 1, 6));
2817 #if TAG_MAJOR_VERSION == 34
2818 if (you.species == SP_DJINNI)
2821 if (cast_healing(pow,
2822 3 + (int) ceil(you.skill(SK_INVOCATIONS, 1) / 6.0),
2823 true, you.pos(), false, TARG_NUM_MODES)
2831 case ABIL_ELYVILON_PURIFICATION:
2833 elyvilon_purification();
2836 case ABIL_ELYVILON_GREATER_HEALING:
2837 case ABIL_ELYVILON_HEAL_OTHER:
2840 const bool self = (abil.ability == ABIL_ELYVILON_GREATER_HEALING);
2842 int pow = 10 + (you.skill_rdiv(SK_INVOCATIONS, 1, 3));
2843 #if TAG_MAJOR_VERSION == 34
2844 if (self && you.species == SP_DJINNI)
2847 if (cast_healing(pow,
2848 10 + (int) ceil(you.skill(SK_INVOCATIONS, 1) / 3.0),
2849 true, self ? you.pos() : coord_def(0, 0), !self,
2850 self ? TARG_NUM_MODES : TARG_INJURED_FRIEND)
2858 case ABIL_ELYVILON_DIVINE_VIGOUR:
2860 if (!elyvilon_divine_vigour())
2864 case ABIL_LUGONU_ABYSS_EXIT:
2866 down_stairs(DNGN_EXIT_ABYSS);
2869 case ABIL_LUGONU_BEND_SPACE:
2871 lugonu_bend_space();
2874 case ABIL_LUGONU_BANISH:
2876 beam.range = LOS_RADIUS;
2877 const int pow = 16 + you.skill(SK_INVOCATIONS, 8);
2879 if (!spell_direction(spd, beam, DIR_NONE, TARG_HOSTILE, 0,
2880 true, true, false, nullptr, nullptr, false, nullptr,
2881 bind(desc_success_chance, placeholders::_1,
2882 zap_ench_power(ZAP_BANISHMENT, pow))))
2887 if (beam.target == you.pos())
2889 mpr("You cannot banish yourself!");
2893 return zapping(ZAP_BANISHMENT, pow, beam, true, nullptr, fail);
2896 case ABIL_LUGONU_CORRUPT:
2898 if (!lugonu_corrupt_level(300 + you.skill(SK_INVOCATIONS, 15)))
2902 case ABIL_LUGONU_ABYSS_ENTER:
2906 dec_hp(random2avg(you.hp, 2), false);
2909 if (you.magic_points)
2910 dec_mp(random2avg(you.magic_points, 2));
2912 bool note_status = notes_are_active();
2913 activate_notes(false); // This banishment shouldn't be noted.
2915 activate_notes(note_status);
2919 case ABIL_NEMELEX_TRIPLE_DRAW:
2921 if (!deck_triple_draw())
2925 case ABIL_NEMELEX_DEAL_FOUR:
2931 case ABIL_NEMELEX_STACK_FIVE:
2937 case ABIL_BEOGH_SMITING:
2939 if (your_spells(SPELL_SMITING, 12 + skill_bump(SK_INVOCATIONS, 6),
2940 false) == SPRET_ABORT)
2946 case ABIL_BEOGH_GIFT_ITEM:
2947 if (!beogh_gift_item())
2951 case ABIL_BEOGH_RECALL_ORCISH_FOLLOWERS:
2953 start_recall(RECALL_BEOGH);
2956 case ABIL_STOP_RECALL:
2958 mpr("You stop recalling your allies.");
2962 case ABIL_FEDHAS_SUNLIGHT:
2963 return fedhas_sunlight(fail);
2965 case ABIL_FEDHAS_PLANT_RING:
2967 if (!fedhas_plant_ring_from_fruit())
2971 case ABIL_FEDHAS_RAIN:
2973 if (!fedhas_rain(you.pos()))
2975 canned_msg(MSG_NOTHING_HAPPENS);
2980 case ABIL_FEDHAS_SPAWN_SPORES:
2982 ASSERT(fedhas_corpse_spores() > 0);
2985 case ABIL_FEDHAS_EVOLUTION:
2987 fedhas_evolve_flora();
2992 if (!transform(100, TRAN_BAT))
2994 crawl_state.zero_turns_taken();
2999 case ABIL_JIYVA_CALL_JELLY:
3002 mgen_data mg(MONS_JELLY, BEH_STRICT_NEUTRAL, 0, 0, 0, you.pos(),
3003 MHITNOT, 0, GOD_JIYVA);
3005 mg.non_actor_summoner = "Jiyva";
3007 if (!create_monster(mg))
3012 case ABIL_JIYVA_JELLY_PARALYSE:
3014 jiyva_paralyse_jellies();
3017 case ABIL_JIYVA_SLIMIFY:
3020 const item_def* const weapon = you.weapon();
3021 const string msg = (weapon) ? weapon->name(DESC_YOUR)
3022 : ("your " + you.hand_name(true));
3023 mprf(MSGCH_DURATION, "A thick mucus forms on %s.", msg.c_str());
3024 you.increase_duration(DUR_SLIMIFY,
3025 random2avg(you.piety / 4, 2) + 3, 100);
3029 case ABIL_JIYVA_CURE_BAD_MUTATION:
3031 jiyva_remove_bad_mutation();
3034 case ABIL_CHEIBRIADOS_TIME_STEP:
3036 cheibriados_time_step(you.skill(SK_INVOCATIONS, 10) * you.piety / 100);
3039 case ABIL_CHEIBRIADOS_TIME_BEND:
3041 cheibriados_time_bend(16 + you.skill(SK_INVOCATIONS, 8));
3044 case ABIL_CHEIBRIADOS_DISTORTION:
3046 cheibriados_temporal_distortion();
3049 case ABIL_CHEIBRIADOS_SLOUCH:
3051 if (!cheibriados_slouch(0))
3058 case ABIL_ASHENZARI_SCRYING:
3060 if (you.duration[DUR_SCRYING])
3061 mpr("You extend your astral sight.");
3063 mpr("You gain astral sight.");
3064 you.duration[DUR_SCRYING] = 100 + random2avg(you.piety * 2, 2);
3065 you.xray_vision = true;
3068 case ABIL_ASHENZARI_TRANSFER_KNOWLEDGE:
3070 if (!ashenzari_transfer_knowledge())
3077 case ABIL_ASHENZARI_END_TRANSFER:
3079 ashenzari_end_transfer();
3082 case ABIL_DITHMENOS_SHADOW_STEP:
3084 if (!dithmenos_shadow_step())
3091 case ABIL_DITHMENOS_SHADOW_FORM:
3093 if (!transform(you.skill(SK_INVOCATIONS, 2), TRAN_SHADOW))
3095 crawl_state.zero_turns_taken();
3100 case ABIL_GOZAG_POTION_PETITION:
3102 run_uncancel(UNC_POTION_PETITION, 0);
3105 case ABIL_GOZAG_CALL_MERCHANT:
3107 run_uncancel(UNC_CALL_MERCHANT, 0);
3110 case ABIL_GOZAG_BRIBE_BRANCH:
3112 if (!gozag_bribe_branch())
3116 case ABIL_QAZLAL_UPHEAVAL:
3117 return qazlal_upheaval(coord_def(), false, fail);
3119 case ABIL_QAZLAL_ELEMENTAL_FORCE:
3121 qazlal_elemental_force();
3124 case ABIL_QAZLAL_DISASTER_AREA:
3126 if (!qazlal_disaster_area())
3130 case ABIL_RU_SACRIFICE_PURITY:
3131 case ABIL_RU_SACRIFICE_WORDS:
3132 case ABIL_RU_SACRIFICE_DRINK:
3133 case ABIL_RU_SACRIFICE_ESSENCE:
3134 case ABIL_RU_SACRIFICE_HEALTH:
3135 case ABIL_RU_SACRIFICE_STEALTH:
3136 case ABIL_RU_SACRIFICE_ARTIFICE:
3137 case ABIL_RU_SACRIFICE_LOVE:
3138 case ABIL_RU_SACRIFICE_COURAGE:
3139 case ABIL_RU_SACRIFICE_ARCANA:
3140 case ABIL_RU_SACRIFICE_NIMBLENESS:
3141 case ABIL_RU_SACRIFICE_DURABILITY:
3142 case ABIL_RU_SACRIFICE_HAND:
3143 case ABIL_RU_SACRIFICE_EXPERIENCE:
3144 case ABIL_RU_SACRIFICE_SKILL:
3146 if (!ru_do_sacrifice(abil.ability))
3150 case ABIL_RU_REJECT_SACRIFICES:
3152 if (!ru_reject_sacrifices())
3156 case ABIL_RU_DRAW_OUT_POWER:
3158 if (you.duration[DUR_EXHAUSTED])
3160 mpr("You're too exhausted to draw out your power.");
3163 if (you.hp == you.hp_max && you.magic_points == you.max_magic_points
3164 && !you.duration[DUR_CONF]
3165 && !you.duration[DUR_SLOW]
3166 && !you.attribute[ATTR_HELD]
3167 && !you.petrifying()
3168 && !you.is_constricted())
3170 mpr("You have no need to draw out power.");
3173 ru_draw_out_power();
3174 you.increase_duration(DUR_EXHAUSTED, 12 + random2(5));
3177 case ABIL_RU_POWER_LEAP:
3179 if (you.duration[DUR_EXHAUSTED])
3181 mpr("You're too exhausted to power leap.");
3184 if (!ru_power_leap())
3189 you.increase_duration(DUR_EXHAUSTED, 18 + random2(8));
3192 case ABIL_RU_APOCALYPSE:
3194 if (you.duration[DUR_EXHAUSTED])
3196 mpr("You're too exhausted to unleash your apocalyptic power.");
3199 if (!ru_apocalypse())
3201 you.increase_duration(DUR_EXHAUSTED, 30 + random2(20));
3204 case ABIL_RENOUNCE_RELIGION:
3206 if (yesno("Really renounce your faith, foregoing its fabulous benefits?",
3208 && yesno("Are you sure you won't change your mind later?",
3220 case ABIL_CONVERT_TO_BEOGH:
3222 god_pitch(GOD_BEOGH);
3223 if (you_worship(GOD_BEOGH))
3225 spare_beogh_convert();
3230 case ABIL_NON_ABILITY:
3232 mpr("Sorry, you can't do that.");
3236 die("invalid ability");
3239 return SPRET_SUCCESS;
3242 // [ds] Increase piety cost for god abilities that are particularly
3243 // overpowered in Sprint. Yes, this is a hack. No, I don't care.
3244 static int _scale_piety_cost(ability_type abil, int original_cost)
3246 // Abilities that have aroused our ire earn 2.5x their classic
3247 // Crawl piety cost.
3248 return (crawl_state.game_is_sprint()
3249 && (abil == ABIL_TROG_BROTHERS_IN_ARMS
3250 || abil == ABIL_MAKHLEB_GREATER_SERVANT_OF_MAKHLEB))
3251 ? div_rand_round(original_cost * 5, 2)
3255 // We pass in ability ZP cost as it may have changed during the exercise
3256 // of the ability (if the cost is scaled, for example)
3257 static void _pay_ability_costs(const ability_def& abil, int zpcost)
3259 if (abil.flags & ABFLAG_INSTANT)
3261 you.turn_is_over = false;
3262 you.elapsed_time_at_last_input = you.elapsed_time;
3263 update_turn_count();
3266 you.turn_is_over = true;
3268 const int food_cost = abil.food_cost + random2avg(abil.food_cost, 2);
3269 const int piety_cost =
3270 _scale_piety_cost(abil.ability, abil.piety_cost.cost());
3271 const int hp_cost = abil.hp_cost.cost(you.hp_max);
3273 dprf("Cost: mp=%d; hp=%d; food=%d; piety=%d",
3274 abil.mp_cost, hp_cost, food_cost, piety_cost);
3278 dec_mp(abil.mp_cost);
3279 if (abil.flags & ABFLAG_PERMANENT_MP)
3285 dec_hp(hp_cost, false);
3286 if (abil.flags & ABFLAG_PERMANENT_HP)
3292 you.zot_points -= zpcost;
3293 you.redraw_experience = true;
3296 if (abil.flags & ABFLAG_NECRO_MISCAST_MINOR)
3298 MiscastEffect(&you, nullptr, ABIL_MISCAST, SPTYP_NECROMANCY, 5, 90,
3299 "power out of control");
3301 if (abil.flags & ABFLAG_LEVEL_DRAIN)
3305 make_hungry(food_cost, false, true);
3308 lose_piety(piety_cost);
3311 int choose_ability_menu(const vector<talent>& talents)
3313 #ifdef USE_TILE_LOCAL
3314 const bool text_only = false;
3316 const bool text_only = true;
3319 ToggleableMenu abil_menu(MF_SINGLESELECT | MF_ANYPRINTABLE
3320 | MF_TOGGLE_ACTION | MF_ALWAYS_SHOW_MORE,
3323 abil_menu.set_highlighter(nullptr);
3324 #ifdef USE_TILE_LOCAL
3326 // Hack like the one in spl-cast.cc:list_spells() to align the title.
3327 ToggleableMenuEntry* me =
3328 new ToggleableMenuEntry(" Ability - do what? "
3330 " Ability - describe what? "
3334 abil_menu.add_entry(me);
3337 abil_menu.set_title(
3338 new ToggleableMenuEntry(" Ability - do what? "
3340 " Ability - describe what? "
3344 abil_menu.set_tag("ability");
3345 abil_menu.add_toggle_key('!');
3346 abil_menu.add_toggle_key('?');
3347 abil_menu.menu_action = Menu::ACT_EXECUTE;
3349 if (crawl_state.game_is_hints())
3351 // XXX: This could be buggy if you manage to pick up lots and
3352 // lots of abilities during hints mode.
3353 abil_menu.set_more(hints_abilities_info());
3357 abil_menu.set_more(formatted_string::parse_string(
3358 "Press '<w>!</w>' or '<w>?</w>' to toggle "
3359 "between ability selection and description."));
3363 for (int i = 0; i < 52; ++i)
3366 bool found_invocations = false;
3367 bool found_zotdef = false;
3369 // First add all non-invocation, non-zotdef abilities.
3370 for (unsigned int i = 0; i < talents.size(); ++i)
3372 if (talents[i].is_invocation)
3373 found_invocations = true;
3374 else if (talents[i].is_zotdef)
3375 found_zotdef = true;
3378 ToggleableMenuEntry* me =
3379 new ToggleableMenuEntry(describe_talent(talents[i]),
3380 describe_talent(talents[i]),
3381 MEL_ITEM, 1, talents[i].hotkey);
3382 me->data = &numbers[i];
3384 me->add_tile(tile_def(tileidx_ability(talents[i].which), TEX_GUI));
3386 // Only check this here, since your god can't hate its own abilities
3387 if (god_hates_ability(talents[i].which, you.religion))
3388 me->colour = COL_FORBIDDEN;
3389 abil_menu.add_entry(me);
3395 #ifdef USE_TILE_LOCAL
3396 ToggleableMenuEntry* subtitle =
3397 new ToggleableMenuEntry(" Zot Defence -",
3398 " Zot Defence -", MEL_ITEM);
3399 subtitle->colour = BLUE;
3400 abil_menu.add_entry(subtitle);
3402 abil_menu.add_entry(
3403 new ToggleableMenuEntry(" Zot Defence - ",
3404 " Zot Defence - ", MEL_SUBTITLE));
3406 for (unsigned int i = 0; i < talents.size(); ++i)
3408 if (talents[i].is_zotdef)
3410 ToggleableMenuEntry* me =
3411 new ToggleableMenuEntry(describe_talent(talents[i]),
3412 describe_talent(talents[i]),
3413 MEL_ITEM, 1, talents[i].hotkey);
3414 me->data = &numbers[i];
3416 me->add_tile(tile_def(tileidx_ability(talents[i].which),
3419 abil_menu.add_entry(me);
3424 if (found_invocations)
3426 #ifdef USE_TILE_LOCAL
3427 ToggleableMenuEntry* subtitle =
3428 new ToggleableMenuEntry(" Invocations - ",
3429 " Invocations - ", MEL_ITEM);
3430 subtitle->colour = BLUE;
3431 abil_menu.add_entry(subtitle);
3433 abil_menu.add_entry(
3434 new ToggleableMenuEntry(" Invocations - ",
3435 " Invocations - ", MEL_SUBTITLE));
3437 for (unsigned int i = 0; i < talents.size(); ++i)
3439 if (talents[i].is_invocation)
3441 ToggleableMenuEntry* me =
3442 new ToggleableMenuEntry(describe_talent(talents[i]),
3443 describe_talent(talents[i]),
3444 MEL_ITEM, 1, talents[i].hotkey);
3445 me->data = &numbers[i];
3447 me->add_tile(tile_def(tileidx_ability(talents[i].which),
3450 abil_menu.add_entry(me);
3457 vector<MenuEntry*> sel = abil_menu.show(false);
3458 if (!crawl_state.doing_prev_cmd_again)
3463 ASSERT(sel.size() == 1);
3464 ASSERT(sel[0]->hotkeys.size() == 1);
3465 int selected = *(static_cast<int*>(sel[0]->data));
3467 if (abil_menu.menu_action == Menu::ACT_EXAMINE)
3468 _print_talent_description(talents[selected]);
3470 return *(static_cast<int*>(sel[0]->data));
3474 string describe_talent(const talent& tal)
3476 ASSERT(tal.which != ABIL_NON_ABILITY);
3478 const string failure = failure_rate_to_string(tal.fail);
3482 << chop_string(ability_name(tal.which), 32)
3483 << chop_string(make_cost_description(tal.which), 30)
3484 << chop_string(failure, 7);
3488 static void _add_talent(vector<talent>& vec, const ability_type ability,
3489 bool check_confused)
3491 const talent t = get_talent(ability, check_confused);
3492 if (t.which != ABIL_NON_ABILITY)
3497 * Return all relevant talents that the player has.
3499 * Currently the only abilities that are affected by include_unusable are god
3500 * abilities (affect by e.g. penance or silence).
3501 * @param check_confused If true, abilities that don't work when confused will
3503 * @param include_unusable If true, abilities that are currently unusable will
3505 * @return A vector of talent structs.
3507 vector<talent> your_talents(bool check_confused, bool include_unusable)
3509 vector<talent> talents;
3511 // zot defence abilities; must also be updated in player.cc when these levels are changed
3512 if (crawl_state.game_is_zotdef())
3514 if (you.experience_level >= 2)
3515 _add_talent(talents, ABIL_MAKE_OKLOB_SAPLING, check_confused);
3516 if (you.experience_level >= 3)
3517 _add_talent(talents, ABIL_MAKE_ARROW_TRAP, check_confused);
3518 if (you.experience_level >= 4)
3519 _add_talent(talents, ABIL_MAKE_PLANT, check_confused);
3520 if (you.experience_level >= 4)
3521 _add_talent(talents, ABIL_REMOVE_CURSE, check_confused);
3522 if (you.experience_level >= 5)
3523 _add_talent(talents, ABIL_MAKE_BURNING_BUSH, check_confused);
3524 if (you.experience_level >= 6)
3525 _add_talent(talents, ABIL_MAKE_ALTAR, check_confused);
3526 if (you.experience_level >= 6)
3527 _add_talent(talents, ABIL_MAKE_GRENADES, check_confused);
3528 if (you.experience_level >= 7)
3529 _add_talent(talents, ABIL_MAKE_OKLOB_PLANT, check_confused);
3530 if (you.experience_level >= 8)
3531 _add_talent(talents, ABIL_MAKE_NET_TRAP, check_confused);
3532 if (you.experience_level >= 9)
3533 _add_talent(talents, ABIL_MAKE_ICE_STATUE, check_confused);
3534 if (you.experience_level >= 10)
3535 _add_talent(talents, ABIL_MAKE_SPEAR_TRAP, check_confused);
3536 if (you.experience_level >= 11)
3537 _add_talent(talents, ABIL_MAKE_ALARM_TRAP, check_confused);
3538 if (you.experience_level >= 12)
3539 _add_talent(talents, ABIL_MAKE_FUNGUS, check_confused);
3540 if (you.experience_level >= 13)
3541 _add_talent(talents, ABIL_MAKE_BOLT_TRAP, check_confused);
3542 if (you.experience_level >= 14)
3543 _add_talent(talents, ABIL_MAKE_OCS, check_confused);
3544 if (you.experience_level >= 15)
3545 _add_talent(talents, ABIL_MAKE_NEEDLE_TRAP, check_confused);
3546 if (you.experience_level >= 16 && !player_has_orb())
3547 _add_talent(talents, ABIL_MAKE_TELEPORT, check_confused);
3548 if (you.experience_level >= 17)
3549 _add_talent(talents, ABIL_MAKE_WATER, check_confused);
3550 if (you.experience_level >= 19)
3551 _add_talent(talents, ABIL_MAKE_LIGHTNING_SPIRE, check_confused);
3552 if (you.experience_level >= 20)
3553 _add_talent(talents, ABIL_MAKE_OBSIDIAN_STATUE, check_confused);
3554 // gain bazaar and gold together
3555 if (you.experience_level >= 21)
3556 _add_talent(talents, ABIL_MAKE_BAZAAR, check_confused);
3557 if (you.experience_level >= 21)
3558 _add_talent(talents, ABIL_MAKE_ACQUIRE_GOLD, check_confused);
3559 if (you.experience_level >= 22)
3560 _add_talent(talents, ABIL_MAKE_OKLOB_CIRCLE, check_confused);
3561 if (you.experience_level >= 24)
3562 _add_talent(talents, ABIL_MAKE_ACQUIREMENT, check_confused);
3563 if (you.experience_level >= 25)
3564 _add_talent(talents, ABIL_MAKE_BLADE_TRAP, check_confused);
3565 if (you.experience_level >= 26)
3566 _add_talent(talents, ABIL_MAKE_CURSE_SKULL, check_confused);
3567 // 27 was: Make teleport trap
3570 // Species-based abilities.
3571 if (player_mutation_level(MUT_MUMMY_RESTORATION))
3572 _add_talent(talents, ABIL_MUMMY_RESTORATION, check_confused);
3574 if (you.species == SP_DEEP_DWARF)
3575 _add_talent(talents, ABIL_RECHARGING, check_confused);
3577 if (you.species == SP_FORMICID
3578 && (you.form != TRAN_TREE || include_unusable))
3580 _add_talent(talents, ABIL_DIG, check_confused);
3581 if ((!crawl_state.game_is_sprint() || brdepth[you.where_are_you] > 1)
3582 && !crawl_state.game_is_zotdef())
3584 _add_talent(talents, ABIL_SHAFT_SELF, check_confused);
3588 // Spit Poison, possibly upgraded to Breathe Poison.
3589 if (player_mutation_level(MUT_SPIT_POISON) == 3)
3590 _add_talent(talents, ABIL_BREATHE_POISON, check_confused);
3591 else if (player_mutation_level(MUT_SPIT_POISON))
3592 _add_talent(talents, ABIL_SPIT_POISON, check_confused);
3594 if (species_is_draconian(you.species)
3595 // Draconians don't maintain their original breath weapons
3596 // if shapechanged into a non-dragon form.
3597 && (!form_changed_physiology() || you.form == TRAN_DRAGON)
3598 && draconian_breath(you.species) != ABIL_NON_ABILITY)
3600 _add_talent(talents, draconian_breath(you.species), check_confused);
3603 if (you.species == SP_VAMPIRE && you.experience_level >= 3
3604 && you.hunger_state <= HS_SATIATED
3605 && you.form != TRAN_BAT)
3607 _add_talent(talents, ABIL_TRAN_BAT, check_confused);
3610 if (player_mutation_level(MUT_TENGU_FLIGHT) && !you.airborne()
3611 || you.racial_permanent_flight() && !you.attribute[ATTR_PERM_FLIGHT]
3612 #if TAG_MAJOR_VERSION == 34
3613 && you.species != SP_DJINNI
3617 // Tengu can fly, but only from the ground
3618 // (until level 14, when it becomes permanent until revoked).
3619 // Black draconians and gargoyles get permaflight at XL 14, but they
3620 // don't get the tengu movement/evasion bonuses and they don't get
3621 // temporary flight before then.
3622 // Other dracs can mutate big wings whenever for temporary flight.
3623 _add_talent(talents, ABIL_FLY, check_confused);
3626 if (you.attribute[ATTR_PERM_FLIGHT] && you.racial_permanent_flight())
3627 _add_talent(talents, ABIL_STOP_FLYING, check_confused);
3630 if (player_mutation_level(MUT_HURL_HELLFIRE))
3631 _add_talent(talents, ABIL_HELLFIRE, check_confused);
3633 if (you.duration[DUR_TRANSFORMATION] && !you.transform_uncancellable)
3634 _add_talent(talents, ABIL_END_TRANSFORMATION, check_confused);
3636 if (player_mutation_level(MUT_BLINK))
3637 _add_talent(talents, ABIL_BLINK, check_confused);
3639 // Religious abilities.
3640 for (ability_type abil : get_god_abilities(include_unusable))
3641 _add_talent(talents, abil, check_confused);
3643 // And finally, the ability to opt-out of your faith {dlb}:
3644 if (!you_worship(GOD_NO_GOD))
3645 _add_talent(talents, ABIL_RENOUNCE_RELIGION, check_confused);
3647 if (env.level_state & LSTATE_BEOGH && can_convert_to_beogh())
3648 _add_talent(talents, ABIL_CONVERT_TO_BEOGH, check_confused);
3650 //jmf: Check for breath weapons - they're exclusive of each other, I hope!
3651 // Make better ones come first.
3652 if (you.species != SP_RED_DRACONIAN &&
3653 ((you.form == TRAN_DRAGON
3654 && dragon_form_dragon_type() == MONS_FIRE_DRAGON)
3655 || player_mutation_level(MUT_BREATHE_FLAMES)))
3657 _add_talent(talents, ABIL_BREATHE_FIRE, check_confused);
3660 // Checking for unreleased Delayed Fireball.
3661 if (you.attribute[ ATTR_DELAYED_FIREBALL ])
3662 _add_talent(talents, ABIL_DELAYED_FIREBALL, check_confused);
3664 if (you.duration[DUR_SONG_OF_SLAYING])
3665 _add_talent(talents, ABIL_STOP_SINGING, check_confused);
3667 // Evocations from items.
3668 if (you.scan_artefacts(ARTP_BLINK)
3669 && !player_mutation_level(MUT_NO_ARTIFICE))
3671 _add_talent(talents, ABIL_EVOKE_BLINK, check_confused);
3674 if (you.scan_artefacts(ARTP_FOG)
3675 && !player_mutation_level(MUT_NO_ARTIFICE))
3677 _add_talent(talents, ABIL_EVOKE_FOG, check_confused);
3680 if (you.evokable_berserk() && !player_mutation_level(MUT_NO_ARTIFICE))
3681 _add_talent(talents, ABIL_EVOKE_BERSERK, check_confused);
3683 if (you.evokable_invis() && !you.attribute[ATTR_INVIS_UNCANCELLABLE]
3684 && !player_mutation_level(MUT_NO_ARTIFICE))
3686 // Now you can only turn invisibility off if you have an
3687 // activatable item. Wands and potions will have to time
3689 if (you.duration[DUR_INVIS])
3690 _add_talent(talents, ABIL_EVOKE_TURN_VISIBLE, check_confused);
3692 _add_talent(talents, ABIL_EVOKE_TURN_INVISIBLE, check_confused);
3695 if (you.evokable_flight() && !player_mutation_level(MUT_NO_ARTIFICE))
3697 // Has no effect on permanently flying Tengu.
3698 if (!you.permanent_flight() || !you.racial_permanent_flight())
3700 // You can still evoke perm flight if you have temporary one.
3702 || !you.attribute[ATTR_PERM_FLIGHT]
3703 && you.wearing_ego(EQ_ALL_ARMOUR, SPARM_FLYING))
3705 _add_talent(talents, ABIL_EVOKE_FLIGHT, check_confused);
3707 // Now you can only turn flight off if you have an
3708 // activatable item. Potions and spells will have to time
3710 if (you.airborne() && !you.attribute[ATTR_FLIGHT_UNCANCELLABLE])
3711 _add_talent(talents, ABIL_STOP_FLYING, check_confused);
3715 if (you.wearing(EQ_RINGS, RING_TELEPORTATION)
3716 && !player_mutation_level(MUT_NO_ARTIFICE)
3717 && !crawl_state.game_is_sprint())
3719 _add_talent(talents, ABIL_EVOKE_TELEPORTATION, check_confused);
3722 if (you.wearing(EQ_RINGS, RING_TELEPORT_CONTROL)
3723 && !player_mutation_level(MUT_NO_ARTIFICE))
3725 _add_talent(talents, ABIL_EVOKE_TELEPORT_CONTROL, check_confused);
3728 if (you.scan_artefacts(ARTP_TWISTER)
3729 && !player_mutation_level(MUT_NO_ARTIFICE))
3731 _add_talent(talents, ABIL_EVOKE_TWISTER, check_confused);
3734 // Find hotkeys for the non-hotkeyed talents.
3735 for (talent &tal : talents)
3737 // Skip preassigned hotkeys.
3738 if (tal.hotkey != 0)
3741 // Try to find a free hotkey for i, starting from Z.
3742 for (int k = 51; k >= 0; ++k)
3744 const int kkey = index_to_letter(k);
3745 bool good_key = true;
3747 // Check that it doesn't conflict with other hotkeys.
3748 for (const talent &other : talents)
3749 if (other.hotkey == kkey)
3758 you.ability_letter_table[k] = tal.which;
3762 // In theory, we could be left with an unreachable ability
3763 // here (if you have 53 or more abilities simultaneously).
3769 // Note: we're trying for a behaviour where the player gets
3770 // to keep their assigned invocation slots if they get excommunicated
3771 // and then rejoin (but if they spend time with another god we consider
3772 // the old invocation slots void and erase them). We also try to
3773 // protect any bindings the character might have made into the
3774 // traditional invocation slots (A-E and X). -- bwr
3775 static void _set_god_ability_helper(ability_type abil, char letter)
3778 const int index = letter_to_index(letter);
3780 for (i = 0; i < 52; i++)
3781 if (you.ability_letter_table[i] == abil)
3784 if (i == 52) // Ability is not already assigned.
3786 // If slot is unoccupied, move in.
3787 if (you.ability_letter_table[index] == ABIL_NON_ABILITY)
3788 you.ability_letter_table[index] = abil;
3792 // Return GOD_NO_GOD if it isn't a god ability, otherwise return
3793 // the index of the god.
3794 static int _is_god_ability(ability_type abil)
3796 if (abil == ABIL_NON_ABILITY)
3799 // Not in god_abilities because players get them at 0*
3800 // TODO: Fix that and remove the following.
3801 if (abil == ABIL_CHEIBRIADOS_TIME_BEND)
3802 return GOD_CHEIBRIADOS;
3803 if (abil == ABIL_TROG_BURN_SPELLBOOKS)
3806 for (int i = 0; i < NUM_GODS; ++i)
3807 for (int j = 0; j < MAX_GOD_ABILITIES; ++j)
3809 if (god_abilities[i][j] == abil)
3816 void set_god_ability_slots()
3818 ASSERT(!you_worship(GOD_NO_GOD));
3820 _set_god_ability_helper(ABIL_RENOUNCE_RELIGION, 'X');
3822 // Clear out other god invocations.
3823 for (int i = 0; i < 52; i++)
3825 const int god = _is_god_ability(you.ability_letter_table[i]);
3826 if (god != GOD_NO_GOD && god != you.religion)
3827 you.ability_letter_table[i] = ABIL_NON_ABILITY;
3830 // Finally, add in current god's invocations in traditional slots.
3832 if (you_worship(GOD_CHEIBRIADOS))
3834 _set_god_ability_helper(ABIL_CHEIBRIADOS_TIME_BEND,
3838 for (int i = 0; i < MAX_GOD_ABILITIES; ++i)
3840 if (god_abilities[you.religion][i] != ABIL_NON_ABILITY)
3842 _set_god_ability_helper(god_abilities[you.religion][i],
3845 if (you_worship(GOD_ELYVILON))
3847 if (god_abilities[you.religion][i]
3848 == ABIL_ELYVILON_LESSER_HEALING)
3850 _set_god_ability_helper(ABIL_ELYVILON_LIFESAVING, 'p');
3853 else if (you_worship(GOD_YREDELEMNUL))
3855 if (god_abilities[you.religion][i]
3856 == ABIL_YRED_RECALL_UNDEAD_SLAVES)
3858 _set_god_ability_helper(ABIL_YRED_INJURY_MIRROR,
3866 // Returns an index (0-51) if successful, -1 if you should
3867 // just use the next one.
3868 static int _find_ability_slot(const ability_def &abil)
3870 for (int slot = 0; slot < 52; slot++)
3871 // Placeholder handling, part 2: The ability we have might
3872 // correspond to a placeholder, in which case the ability letter
3873 // table will contain that placeholder. Convert the latter to
3874 // its corresponding ability before comparing the two, so that
3875 // we'll find the placeholder's index properly.
3876 if (_fixup_ability(you.ability_letter_table[slot]) == abil.ability)
3879 // No requested slot, find new one and make it preferred.
3881 // Skip over a-e (invocations), a-g for Elyvilon, a-E for ZotDef
3882 int first_slot = letter_to_index('f');
3883 if (you_worship(GOD_ELYVILON))
3884 first_slot = letter_to_index('h');
3885 if (abil.flags & ABFLAG_ZOTDEF)
3886 first_slot = letter_to_index('F'); // for *some* memory compat.
3888 if (abil.ability == ABIL_ZIN_CURE_ALL_MUTATIONS)
3889 first_slot = letter_to_index('W');
3890 if (abil.ability == ABIL_CONVERT_TO_BEOGH)
3891 first_slot = letter_to_index('Y');
3892 if (abil.ability == ABIL_RU_SACRIFICE_PURITY
3893 || abil.ability == ABIL_RU_SACRIFICE_WORDS
3894 || abil.ability == ABIL_RU_SACRIFICE_DRINK
3895 || abil.ability == ABIL_RU_SACRIFICE_ESSENCE
3896 || abil.ability == ABIL_RU_SACRIFICE_HEALTH
3897 || abil.ability == ABIL_RU_SACRIFICE_STEALTH
3898 || abil.ability == ABIL_RU_SACRIFICE_ARTIFICE
3899 || abil.ability == ABIL_RU_SACRIFICE_LOVE
3900 || abil.ability == ABIL_RU_SACRIFICE_COURAGE
3901 || abil.ability == ABIL_RU_SACRIFICE_ARCANA
3902 || abil.ability == ABIL_RU_SACRIFICE_NIMBLENESS
3903 || abil.ability == ABIL_RU_SACRIFICE_DURABILITY
3904 || abil.ability == ABIL_RU_SACRIFICE_HAND
3905 || abil.ability == ABIL_RU_SACRIFICE_EXPERIENCE
3906 || abil.ability == ABIL_RU_SACRIFICE_SKILL
3907 || abil.ability == ABIL_RU_REJECT_SACRIFICES)
3909 first_slot = letter_to_index('P');
3913 for (int slot = first_slot; slot < 52; ++slot)
3915 if (you.ability_letter_table[slot] == ABIL_NON_ABILITY)
3917 you.ability_letter_table[slot] = abil.ability;
3922 // If we can't find anything else, try a-e.
3923 for (int slot = first_slot - 1; slot >= 0; --slot)
3925 if (you.ability_letter_table[slot] == ABIL_NON_ABILITY)
3927 you.ability_letter_table[slot] = abil.ability;
3932 // All letters are assigned.
3936 vector<ability_type> get_god_abilities(bool include_unusable, bool ignore_piety)
3938 vector<ability_type> abilities;
3939 if (you_worship(GOD_TROG) && (include_unusable || !silenced(you.pos())))
3940 abilities.push_back(ABIL_TROG_BURN_SPELLBOOKS);
3941 else if (you_worship(GOD_CHEIBRIADOS) && (include_unusable
3942 || !(silenced(you.pos())
3943 || player_under_penance())))
3945 abilities.push_back(ABIL_CHEIBRIADOS_TIME_BEND);
3947 else if (you_worship(GOD_RU))
3950 ASSERT(you.props.exists(AVAILABLE_SAC_KEY));
3951 CrawlVector &available_sacrifices
3952 = you.props[AVAILABLE_SAC_KEY].get_vector();
3954 int num_sacrifices = available_sacrifices.size();
3955 for (int i = 0; i < num_sacrifices; ++i)
3957 abilities.push_back(
3958 static_cast<ability_type>(available_sacrifices[i].get_int()));
3960 if (num_sacrifices > 0)
3961 abilities.push_back(ABIL_RU_REJECT_SACRIFICES);
3963 else if (you.transfer_skill_points > 0)
3964 abilities.push_back(ABIL_ASHENZARI_END_TRANSFER);
3966 // Remaining abilities are unusable if under penance, or if silenced.
3967 if (!include_unusable && (player_under_penance() || silenced(you.pos())))
3970 for (int i = 0; i < MAX_GOD_ABILITIES; ++i)
3972 if (!you_worship(GOD_GOZAG) && you.piety < piety_breakpoint(i)
3978 const ability_type abil =
3979 _fixup_ability(god_abilities[you.religion][i]);
3980 if (abil == ABIL_NON_ABILITY
3981 || brdepth[BRANCH_ABYSS] == -1
3982 && (abil == ABIL_LUGONU_ABYSS_EXIT
3983 || abil == ABIL_LUGONU_ABYSS_ENTER))
3988 abilities.push_back(abil);
3989 if (abil == ABIL_ELYVILON_LESSER_HEALING)
3990 abilities.push_back(ABIL_ELYVILON_LIFESAVING);
3991 else if (abil == ABIL_YRED_RECALL_UNDEAD_SLAVES
3992 || abil == ABIL_STOP_RECALL && you_worship(GOD_YREDELEMNUL))
3994 abilities.push_back(ABIL_YRED_INJURY_MIRROR);
3998 if (can_do_capstone_ability(GOD_ZIN))
3999 abilities.push_back(ABIL_ZIN_CURE_ALL_MUTATIONS);
4004 ////////////////////////////////////////////////////////////////////////
4007 int generic_cost::cost() const
4009 return base + (add > 0 ? random2avg(add, rolls) : 0);
4012 int scaling_cost::cost(int max) const
4014 return (value < 0) ? (-value) : ((value * max + 500) / 1000);