Apply the new ground_level method.
[crawl.git] / crawl-ref / source / art-func.h
blobd4708ef6b4405ece3aa7631174be669824c4bd35
1 /*
2 * File: art-func.h
3 * Summary: Functions non-standard unrandarts uses.
4 * Written by: Matthew Cline
5 */
7 /*
8 * util/art-data.pl scans through this file to grab the functions
9 * non-standard unrandarts use and put them into the unranddata structs
10 * in art-data.h, so the function names must have the form of
11 * _UNRAND_ENUM_func_name() in order to be recognised.
14 #ifdef ART_FUNC_H
15 #error "art-func.h included twice!"
16 #endif
18 #ifdef ART_DATA_H
19 #error "art-func.h must be included before art-data.h"
20 #endif
22 #define ART_FUNC_H
24 #include "cloud.h" // For storm bow's and robe of clouds' rain
25 #include "effects.h" // For Sceptre of Torment tormenting
26 #include "env.h" // For storm bow env.cgrid
27 #include "food.h" // For evokes
28 #include "godconduct.h" // did_god_conduct.
29 #include "mgen_data.h" // For Sceptre of Asmodeus evoke
30 #include "mon-place.h" // For Sceptre of Asmodeus evoke
31 #include "mon-stuff.h" // For Scythe of Curses cursing items
32 #include "spl-cast.h" // For evokes
33 #include "spl-miscast.h" // For Staff of Wucad Mu miscasts
34 #include "spl-summoning.h" // For Zonguldrok animating dead
35 #include "terrain.h" // For storm bow.
37 /*******************
38 * Helper functions.
39 *******************/
41 static void _equip_mpr(bool* show_msgs, const char* msg,
42 msg_channel_type chan = MSGCH_PLAIN)
44 bool def_show = true;
46 if (show_msgs == NULL)
47 show_msgs = &def_show;
49 if (*show_msgs)
50 mpr(msg, chan);
52 // Caller shouldn't give any more messages.
53 *show_msgs = false;
56 /*******************
57 * Unrand functions.
58 *******************/
60 static void _ASMODEUS_melee_effect(item_def* weapon, actor* attacker,
61 actor* defender, bool mondied)
63 if (attacker->atype() == ACT_PLAYER)
65 did_god_conduct(DID_UNHOLY, 3);
69 static bool _evoke_sceptre_of_asmodeus()
71 bool rc = true;
72 if (one_chance_in(21))
73 rc = false;
74 else if (one_chance_in(20))
76 // Summon devils, maybe a Fiend.
77 const monster_type mon = (one_chance_in(4) ? MONS_FIEND :
78 summon_any_demon(DEMON_COMMON));
79 const bool good_summon = create_monster(
80 mgen_data::hostile_at(mon,
81 "the Sceptre of Asmodeus",
82 true, 6, 0, you.pos())) != -1;
84 if (good_summon)
86 if (mon == MONS_FIEND)
87 mpr("\"Your arrogance condemns you, mortal!\"");
88 else
89 mpr("The Sceptre summons one of its servants.");
91 else
92 mpr("The air shimmers briefly.");
94 else
96 // Cast a destructive spell.
97 const spell_type spl = static_cast<spell_type>(
98 random_choose_weighted(114, SPELL_BOLT_OF_FIRE,
99 57, SPELL_LIGHTNING_BOLT,
100 57, SPELL_BOLT_OF_DRAINING,
101 12, SPELL_HELLFIRE,
102 0));
103 your_spells(spl, you.skills[SK_EVOCATIONS] * 8, false);
106 return (rc);
110 static bool _ASMODEUS_evoke(item_def *item, int* pract, bool* did_work,
111 bool* unevokable)
113 if (_evoke_sceptre_of_asmodeus())
115 make_hungry(200, false, true);
116 *did_work = true;
117 *pract = 1;
120 return (false);
123 ////////////////////////////////////////////////////
125 // XXX: Defender's resistance to fire being temporarily downgraded is
126 // hardcoded in melee_attack::fire_res_apply_cerebov_downgrade()
128 static void _CEREBOV_melee_effect(item_def* weapon, actor* attacker,
129 actor* defender, bool mondied)
131 if (attacker->atype() == ACT_PLAYER)
133 did_god_conduct(DID_UNHOLY, 3);
137 ////////////////////////////////////////////////////
139 static void _CURSES_equip(item_def *item, bool *show_msgs, bool unmeld)
141 _equip_mpr(show_msgs, "A shiver runs down your spine.");
144 static void _CURSES_world_reacts(item_def *item)
146 if (one_chance_in(30))
147 curse_an_item(false);
150 static void _CURSES_melee_effect(item_def* weapon, actor* attacker,
151 actor* defender, bool mondied)
153 if (attacker->atype() == ACT_PLAYER)
155 did_god_conduct(DID_NECROMANCY, 3);
159 /////////////////////////////////////////////////////
161 static void _DISPATER_melee_effect(item_def* weapon, actor* attacker,
162 actor* defender, bool mondied)
164 if (attacker->atype() == ACT_PLAYER)
166 did_god_conduct(DID_UNHOLY, 3);
170 static bool _DISPATER_evoke(item_def *item, int* pract, bool* did_work,
171 bool* unevokable)
173 if (you.duration[DUR_DEATHS_DOOR] || !enough_hp(11, true)
174 || !enough_mp(5, true))
176 return (false);
179 mpr("You feel the staff feeding on your energy!");
181 dec_hp(5 + random2avg(19, 2), false, "Staff of Dispater");
182 dec_mp(2 + random2avg(5, 2));
183 make_hungry(100, false, true);
185 int power = you.skills[SK_EVOCATIONS] * 8;
186 your_spells(SPELL_HELLFIRE, power, false);
188 *pract = (coinflip() ? 2 : 1);
189 *did_work = true;
191 return (false);
194 ////////////////////////////////////////////////////
196 // XXX: Staff giving a boost to poison spells is hardcoded in
197 // player_spec_poison()
199 static void _olgreb_pluses(item_def *item)
201 // Giving Olgreb's staff a little lift since staves of poison have
202 // been made better. -- bwr
203 item->plus = you.skills[SK_POISON_MAGIC] / 3;
204 item->plus2 = item->plus;
207 static void _OLGREB_equip(item_def *item, bool *show_msgs, bool unmeld)
209 if (you.can_smell())
210 _equip_mpr(show_msgs, "You smell chlorine.");
211 else
212 _equip_mpr(show_msgs, "The staff glows a sickly green.");
214 _olgreb_pluses(item);
217 static void _OLGREB_unequip(const item_def *item, bool *show_msgs)
219 if (you.can_smell())
220 _equip_mpr(show_msgs, "The smell of chlorine vanishes.");
221 else
222 _equip_mpr(show_msgs, "The staff's sickly green glow vanishes.");
225 static void _OLGREB_world_reacts(item_def *item)
227 _olgreb_pluses(item);
230 static bool _OLGREB_evoke(item_def *item, int* pract, bool* did_work,
231 bool* unevokable)
233 if (!enough_mp(4, true) || you.skills[SK_EVOCATIONS] < random2(6))
234 return (false);
236 dec_mp(4);
237 make_hungry(50, false, true);
238 *pract = 1;
239 *did_work = true;
241 int power = 10 + you.skills[SK_EVOCATIONS] * 8;
243 your_spells(SPELL_OLGREBS_TOXIC_RADIANCE, power, false);
245 if (x_chance_in_y(you.skills[SK_EVOCATIONS] + 1, 10))
246 your_spells(SPELL_VENOM_BOLT, power, false);
248 return (false);
251 static void _OLGREB_melee_effect(item_def* weapon, actor* attacker,
252 actor* defender, bool mondied)
254 if (defender->alive()
255 && (coinflip() || x_chance_in_y(you.skills[SK_POISON_MAGIC], 8)))
257 defender->poison(attacker, 2, defender->has_lifeforce()
258 && one_chance_in(4));
259 if (attacker->atype() == ACT_PLAYER)
260 did_god_conduct(DID_POISON, 3);
264 ////////////////////////////////////////////////////
266 static void _power_pluses(item_def *item)
268 item->plus = stepdown_value(-4 + (you.hp / 5), 4, 4, 4, 20);
269 item->plus2 = item->plus;
272 static void _POWER_equip(item_def *item, bool *show_msgs, bool unmeld)
274 _equip_mpr(show_msgs, "You sense an aura of extreme power.");
275 _power_pluses(item);
278 static void _POWER_world_reacts(item_def *item)
280 _power_pluses(item);
283 ////////////////////////////////////////////////////
285 static void _SINGING_SWORD_equip(item_def *item, bool *show_msgs, bool unmeld)
287 bool def_show = true;
289 if (show_msgs == NULL)
290 show_msgs = &def_show;
292 if (!*show_msgs)
293 return;
295 if (!item_type_known(*item))
297 mprf(MSGCH_TALK, "%s says, \"Hi! I'm the Singing Sword!\"",
298 item->name(DESC_CAP_THE).c_str());
300 else
301 mpr("The Singing Sword hums in delight!", MSGCH_TALK);
303 *show_msgs = false;
306 static void _SINGING_SWORD_unequip(const item_def *item, bool *show_msgs)
308 _equip_mpr(show_msgs, "The Singing Sword sighs.", MSGCH_TALK);
311 ////////////////////////////////////////////////////
313 static void _PRUNE_equip(item_def *item, bool *show_msgs, bool unmeld)
315 _equip_mpr(show_msgs, "You feel pruney.");
318 ////////////////////////////////////////////////////
320 static void _TORMENT_equip(item_def *item, bool *show_msgs, bool unmeld)
322 _equip_mpr(show_msgs, "A terribly searing pain shoots up your arm!");
325 static void _TORMENT_world_reacts(item_def *item)
327 if (one_chance_in(200))
329 torment(TORMENT_SPWLD, you.pos());
330 did_god_conduct(DID_UNHOLY, 1);
334 static void _TORMENT_melee_effect(item_def* weapon, actor* attacker,
335 actor* defender, bool mondied)
337 if (attacker->atype() == ACT_PLAYER && coinflip())
339 torment(TORMENT_SPWLD, you.pos());
340 did_god_conduct(DID_UNHOLY, 5);
344 /////////////////////////////////////////////////////
346 static void _TROG_equip(item_def *item, bool *show_msgs, bool unmeld)
348 _equip_mpr(show_msgs, "You feel bloodthirsty!");
351 static void _TROG_unequip(const item_def *item, bool *show_msgs)
353 _equip_mpr(show_msgs, "You feel less violent.");
356 static void _TROG_melee_effect(item_def* weapon, actor* attacker,
357 actor* defender, bool mondied)
359 if (coinflip())
360 attacker->go_berserk(false);
363 ////////////////////////////////////////////////////
365 static void _wucad_miscast(actor* victim, int power,int fail)
367 MiscastEffect(victim, WIELD_MISCAST, SPTYP_DIVINATION, power, fail,
368 "the Staff of Wucad Mu", NH_NEVER);
371 static void _wucad_pluses(item_def *item)
373 item->plus = std::min(you.intel() - 3, 22);
374 item->plus2 = std::min(you.intel() / 2, 13);
377 static void _WUCAD_MU_equip(item_def *item, bool *show_msgs, bool unmeld)
379 _wucad_pluses(item);
382 static void _WUCAD_MU_world_reacts(item_def *item)
384 _wucad_pluses(item);
387 static bool _WUCAD_MU_evoke(item_def *item, int* pract, bool* did_work,
388 bool* unevokable)
390 if (you.magic_points == you.max_magic_points
391 || you.skills[SK_EVOCATIONS] < random2(25))
393 return (false);
396 mpr("Magical energy flows into your mind!");
398 inc_mp(3 + random2(5) + you.skills[SK_EVOCATIONS] / 3, false);
399 make_hungry(50, false, true);
401 *pract = 1;
402 *did_work = true;
404 if (one_chance_in(3))
405 _wucad_miscast(&you, random2(9), random2(70));
407 return (false);
410 ///////////////////////////////////////////////////
412 // XXX: Always getting maximal vampiric drain is hardcoded in
413 // melee_attack::apply_damage_brand()
415 static void _VAMPIRES_TOOTH_equip(item_def *item, bool *show_msgs, bool unmeld)
417 if (you.is_undead != US_UNDEAD)
419 _equip_mpr(show_msgs,
420 "You feel a strange hunger, and smell blood in the air...");
421 make_hungry(4500, false, false);
423 else
424 _equip_mpr(show_msgs, "You feel strangely empty.");
427 ///////////////////////////////////////////////////
429 // XXX: Pluses at creation time are hardcoded in make_item_unrandart()
431 static void _VARIABILITY_world_reacts(item_def *item)
433 do_uncurse_item(*item);
435 if (x_chance_in_y(2, 5))
436 item->plus += (coinflip() ? +1 : -1);
438 if (x_chance_in_y(2, 5))
439 item->plus2 += (coinflip() ? +1 : -1);
441 if (item->plus < -4)
442 item->plus = -4;
443 else if (item->plus > 16)
444 item->plus = 16;
446 if (item->plus2 < -4)
447 item->plus2 = -4;
448 else if (item->plus2 > 16)
449 item->plus2 = 16;
452 ///////////////////////////////////////////////////
454 static void _ZONGULDROK_equip(item_def *item, bool *show_msgs, bool unmeld)
456 _equip_mpr(show_msgs, "You sense an extremely unholy aura.");
459 static void _ZONGULDROK_world_reacts(item_def *item)
461 if (one_chance_in(5))
463 animate_dead(&you, 1 + random2(3), BEH_HOSTILE, MHITYOU, 0,
464 "the Sword of Zonguldrok");
465 did_god_conduct(DID_NECROMANCY, 1);
466 did_god_conduct(DID_CORPSE_VIOLATION, 1);
470 static void _ZONGULDROK_melee_effect(item_def* weapon, actor* attacker,
471 actor* defender, bool mondied)
473 if (attacker->atype() == ACT_PLAYER)
475 did_god_conduct(DID_NECROMANCY, 3);
476 did_god_conduct(DID_CORPSE_VIOLATION, 3);
480 ///////////////////////////////////////////////////
482 static void _STORM_BOW_world_reacts(item_def *item)
484 if (!one_chance_in(300))
485 return;
487 for (radius_iterator ri(you.pos(), 2); ri; ++ri)
488 if (!cell_is_solid(*ri) && env.cgrid(*ri) == EMPTY_CLOUD && one_chance_in(5))
489 place_cloud(CLOUD_RAIN, *ri, random2(20), &you, 3);
492 ///////////////////////////////////////////////////
494 static void _GONG_melee_effect(item_def* item, actor* wearer,
495 actor* attacker, bool dummy)
497 if (silenced(wearer->pos()))
498 return;
500 std::string msg = getSpeakString("shield of the gong");
501 if (msg.empty())
502 msg = "You hear a strange loud sound.";
503 mpr(msg.c_str(), MSGCH_SOUND);
505 noisy(40, wearer->pos());
508 ///////////////////////////////////////////////////
510 static void _RCLOUDS_world_reacts(item_def *item)
512 cloud_type cloud;
513 if (one_chance_in(4))
514 cloud = CLOUD_RAIN;
515 else
516 cloud = CLOUD_MIST;
518 for (radius_iterator ri(you.pos(), 2); ri; ++ri)
519 if (!cell_is_solid(*ri) && env.cgrid(*ri) == EMPTY_CLOUD
520 && one_chance_in(20))
522 place_cloud(cloud, *ri, random2(10), &you, 1);
526 static void _RCLOUDS_equip(item_def *item, bool *show_msgs, bool unmeld)
528 _equip_mpr(show_msgs, "A thin mist springs up around you!");