/* * File: art-func.h * Summary: Functions non-standard unrandarts uses. * Written by: Matthew Cline */ /* * util/art-data.pl scans through this file to grab the functions * non-standard unrandarts use and put them into the unranddata structs * in art-data.h, so the function names must have the form of * _UNRAND_ENUM_func_name() in order to be recognised. */ #ifdef ART_FUNC_H #error "art-func.h included twice!" #endif #ifdef ART_DATA_H #error "art-func.h must be included before art-data.h" #endif #define ART_FUNC_H #include "cloud.h" // For storm's bow rain #include "effects.h" // For Sceptre of Torment tormenting #include "env.h" // For storm bow env.cgrid #include "food.h" // For evokes #include "mgen_data.h" // For Sceptre of Asmodeus evoke #include "mon-place.h" // For Sceptre of Asmodeus evoke #include "mon-stuff.h" // For Scythe of Curses cursing items #include "spells3.h" // For Zonguldrok animating dead #include "spl-cast.h" // For evokes #include "spl-mis.h" // For Staff of Wucad Mu miscasts #include "terrain.h" // For storm bow. /******************* * Helper functions. *******************/ static void _equip_mpr(bool* show_msgs, const char* msg, msg_channel_type chan = MSGCH_PLAIN) { bool def_show = true; if (show_msgs == NULL) show_msgs = &def_show; if (*show_msgs) mpr(msg, chan); // Caller shouldn't give any more messages. *show_msgs = false; } /******************* * Unrand functions. *******************/ static void _ASMODEUS_melee_effect(item_def* weapon, actor* attacker, actor* defender, bool mondied) { if (attacker->atype() == ACT_PLAYER) { did_god_conduct(DID_UNHOLY, 3); } } static bool _evoke_sceptre_of_asmodeus() { bool rc = true; if (one_chance_in(21)) rc = false; else if (one_chance_in(20)) { // Summon devils, maybe a Fiend. const monster_type mon = (one_chance_in(4) ? MONS_FIEND : summon_any_demon(DEMON_COMMON)); const bool good_summon = create_monster( mgen_data::hostile_at(mon, "the Sceptre of Asmodeus", true, 6, 0, you.pos())) != -1; if (good_summon) { if (mon == MONS_FIEND) mpr("\"Your arrogance condemns you, mortal!\""); else mpr("The Sceptre summons one of its servants."); } else mpr("The air shimmers briefly."); } else { // Cast a destructive spell. const spell_type spl = static_cast( random_choose_weighted(114, SPELL_BOLT_OF_FIRE, 57, SPELL_LIGHTNING_BOLT, 57, SPELL_BOLT_OF_DRAINING, 12, SPELL_HELLFIRE, 0)); your_spells(spl, you.skills[SK_EVOCATIONS] * 8, false); } return (rc); } static bool _ASMODEUS_evoke(item_def *item, int* pract, bool* did_work, bool* unevokable) { if (_evoke_sceptre_of_asmodeus()) { make_hungry(200, false, true); *did_work = true; *pract = 1; } return (false); } //////////////////////////////////////////////////// // XXX: Defender's resistance to fire being temporarily downgraded is // hardcoded in melee_attack::fire_res_apply_cerebov_downgrade() static void _CEREBOV_melee_effect(item_def* weapon, actor* attacker, actor* defender, bool mondied) { if (attacker->atype() == ACT_PLAYER) { did_god_conduct(DID_UNHOLY, 3); } } //////////////////////////////////////////////////// static void _CURSES_equip(item_def *item, bool *show_msgs, bool unmeld) { _equip_mpr(show_msgs, "A shiver runs down your spine."); } static void _CURSES_world_reacts(item_def *item) { if (one_chance_in(30)) curse_an_item(false); } static void _CURSES_melee_effect(item_def* weapon, actor* attacker, actor* defender, bool mondied) { if (attacker->atype() == ACT_PLAYER) { did_god_conduct(DID_NECROMANCY, 3); } } ///////////////////////////////////////////////////// static void _DISPATER_melee_effect(item_def* weapon, actor* attacker, actor* defender, bool mondied) { if (attacker->atype() == ACT_PLAYER) { did_god_conduct(DID_UNHOLY, 3); } } static bool _DISPATER_evoke(item_def *item, int* pract, bool* did_work, bool* unevokable) { if (you.duration[DUR_DEATHS_DOOR] || !enough_hp(11, true) || !enough_mp(5, true)) { return (false); } mpr("You feel the staff feeding on your energy!"); dec_hp( 5 + random2avg(19, 2), false, "Staff of Dispater" ); dec_mp( 2 + random2avg(5, 2) ); make_hungry(100, false, true); int power = you.skills[SK_EVOCATIONS] * 8; your_spells( SPELL_HELLFIRE, power, false ); *pract = (coinflip() ? 2 : 1); *did_work = true; return (false); } //////////////////////////////////////////////////// // XXX: Staff giving a boost to poison spells is hardcoded in // player_spec_poison() static void _olgreb_pluses(item_def *item) { // Giving Olgreb's staff a little lift since staves of poison have // been made better. -- bwr item->plus = you.skills[SK_POISON_MAGIC] / 3; item->plus2 = item->plus; } static void _OLGREB_equip(item_def *item, bool *show_msgs, bool unmeld) { if (you.can_smell()) _equip_mpr(show_msgs, "You smell chlorine."); else _equip_mpr(show_msgs, "The staff glows a sickly green."); _olgreb_pluses(item); } static void _OLGREB_unequip(const item_def *item, bool *show_msgs) { if (you.can_smell()) _equip_mpr(show_msgs, "The smell of chlorine vanishes."); else _equip_mpr(show_msgs, "The staff's sickly green glow vanishes."); } static void _OLGREB_world_reacts(item_def *item) { _olgreb_pluses(item); } static bool _OLGREB_evoke(item_def *item, int* pract, bool* did_work, bool* unevokable) { if (!enough_mp( 4, true ) || you.skills[SK_EVOCATIONS] < random2(6)) return (false); dec_mp(4); make_hungry(50, false, true); *pract = 1; *did_work = true; int power = 10 + you.skills[SK_EVOCATIONS] * 8; your_spells( SPELL_OLGREBS_TOXIC_RADIANCE, power, false ); if (x_chance_in_y(you.skills[SK_EVOCATIONS] + 1, 10)) your_spells( SPELL_VENOM_BOLT, power, false ); return (false); } //////////////////////////////////////////////////// static void _power_pluses(item_def *item) { item->plus = stepdown_value( -4 + (you.hp / 5), 4, 4, 4, 20 ); item->plus2 = item->plus; } static void _POWER_equip(item_def *item, bool *show_msgs, bool unmeld) { _equip_mpr(show_msgs, "You sense an aura of extreme power."); _power_pluses(item); } static void _POWER_world_reacts(item_def *item) { _power_pluses(item); } //////////////////////////////////////////////////// static void _SINGING_SWORD_equip(item_def *item, bool *show_msgs, bool unmeld) { bool def_show = true; if (show_msgs == NULL) show_msgs = &def_show; if (!*show_msgs) return; if (item_type_known(*item)) { mprf(MSGCH_TALK, "%s says, \"Hi! I'm the Singing Sword!\"", item->name(DESC_CAP_THE).c_str()); } else mpr("The Singing Sword hums in delight!", MSGCH_TALK); *show_msgs = false; } static void _SINGING_SWORD_unequip(const item_def *item, bool *show_msgs) { _equip_mpr(show_msgs, "The Singing Sword sighs.", MSGCH_TALK); } //////////////////////////////////////////////////// static void _PRUNE_equip(item_def *item, bool *show_msgs, bool unmeld) { _equip_mpr(show_msgs, "You feel pruney."); } //////////////////////////////////////////////////// static void _TORMENT_equip(item_def *item, bool *show_msgs, bool unmeld) { _equip_mpr(show_msgs, "A terribly searing pain shoots up your arm!"); } static void _TORMENT_world_reacts(item_def *item) { if (one_chance_in(200)) { torment(TORMENT_SPWLD, you.pos()); did_god_conduct(DID_UNHOLY, 1); } } static void _TORMENT_melee_effect(item_def* weapon, actor* attacker, actor* defender, bool mondied) { if (attacker->atype() == ACT_PLAYER && coinflip()) { torment(TORMENT_SPWLD, you.pos()); did_god_conduct(DID_UNHOLY, 5); } } ///////////////////////////////////////////////////// static void _TROG_equip(item_def *item, bool *show_msgs, bool unmeld) { _equip_mpr(show_msgs, "You feel bloodthirsty!"); } static void _TROG_unequip(const item_def *item, bool *show_msgs) { _equip_mpr(show_msgs, "You feel less violent."); } static void _TROG_melee_effect(item_def* weapon, actor* attacker, actor* defender, bool mondied) { if (coinflip()) attacker->go_berserk(false); } //////////////////////////////////////////////////// static void _wucad_miscast(actor* victim, int power,int fail) { MiscastEffect(victim, WIELD_MISCAST, SPTYP_DIVINATION, power, fail, "the Staff of Wucad Mu", NH_NEVER); } static void _wucad_pluses(item_def *item) { item->plus = std::min(you.intel - 3, 22); item->plus2 = std::min(you.intel / 2, 13); } static void _WUCAD_MU_equip(item_def *item, bool *show_msgs, bool unmeld) { _wucad_miscast(&you, 9, 90); _wucad_pluses(item); } static void _WUCAD_MU_unequip(const item_def *item, bool *show_msgs) { _wucad_miscast(&you, 9, 90); } static void _WUCAD_MU_world_reacts(item_def *item) { _wucad_pluses(item); } static void _WUCAD_MU_melee_effect(item_def* weapon, actor* attacker, actor* defender, bool mondied) { if (one_chance_in(9)) _wucad_miscast(attacker, random2(9), random2(70)); } static bool _WUCAD_MU_evoke(item_def *item, int* pract, bool* did_work, bool* unevokable) { if (you.magic_points == you.max_magic_points || you.skills[SK_EVOCATIONS] < random2(25)) { return (false); } mpr("Magical energy flows into your mind!"); inc_mp( 3 + random2(5) + you.skills[SK_EVOCATIONS] / 3, false ); make_hungry(50, false, true); *pract = 1; *did_work = true; if (one_chance_in(3)) _wucad_miscast(&you, random2(9), random2(70)); return (false); } /////////////////////////////////////////////////// // XXX: Always getting maximal vampiric drain is hardcoded in // melee_attack::apply_damage_brand() static void _VAMPIRES_TOOTH_equip(item_def *item, bool *show_msgs, bool unmeld) { if (you.is_undead != US_UNDEAD) { _equip_mpr(show_msgs, "You feel a strange hunger, and smell blood in the air..."); } else _equip_mpr(show_msgs, "You feel strangely empty."); // Vampire's Tooth imposes more hunger than a normal vampiric // weapon. Like other vampiric weapons, the hunger is less for // vampires than for other species. if (you.species != SP_VAMPIRE) artefact_set_property(*item, ARTP_METABOLISM, 3); else artefact_set_property(*item, ARTP_METABOLISM, 1); } /////////////////////////////////////////////////// // XXX: Pluses at creation time are hardcoded in make_item_unrandart() static void _VARIABILITY_world_reacts(item_def *item) { do_uncurse_item(*item); if (x_chance_in_y(2, 5)) item->plus += (coinflip() ? +1 : -1); if (x_chance_in_y(2, 5)) item->plus2 += (coinflip() ? +1 : -1); if (item->plus < -4) item->plus = -4; else if (item->plus > 16) item->plus = 16; if (item->plus2 < -4) item->plus2 = -4; else if (item->plus2 > 16) item->plus2 = 16; } /////////////////////////////////////////////////// static void _ZONGULDROK_equip(item_def *item, bool *show_msgs, bool unmeld) { _equip_mpr(show_msgs, "You sense an extremely unholy aura."); } static void _ZONGULDROK_world_reacts(item_def *item) { if (one_chance_in(5)) { animate_dead(&you, 1 + random2(3), BEH_HOSTILE, MHITYOU, 0, "the Sword of Zonguldrok"); did_god_conduct(DID_NECROMANCY, 1); } } static void _ZONGULDROK_melee_effect(item_def* weapon, actor* attacker, actor* defender, bool mondied) { if (attacker->atype() == ACT_PLAYER) { did_god_conduct(DID_NECROMANCY, 3); } } /////////////////////////////////////////////////// static void _STORM_BOW_world_reacts(item_def *item) { if (!one_chance_in(300)) return; for (radius_iterator ri(you.pos(), 2); ri; ++ri) if (!cell_is_solid(*ri) && env.cgrid(*ri) == EMPTY_CLOUD && one_chance_in(5)) place_cloud( CLOUD_RAIN, *ri, random2(20), KC_OTHER, 3); } /////////////////////////////////////////////////// static void _GONG_melee_effect(item_def* item, actor* wearer, actor* attacker, bool dummy) { if (silenced(wearer->pos())) return; std::string msg = getSpeakString("shield of the gong"); if (msg.empty()) msg = "You hear a strange loud sound."; mpr(msg.c_str(), MSGCH_SOUND); noisy(40, wearer->pos()); } /////////////////////////////////////////////////// static void _RCLOUDS_world_reacts(item_def *item) { cloud_type cloud; if (one_chance_in(4)) cloud = CLOUD_RAIN; else cloud = CLOUD_MIST; for (radius_iterator ri(you.pos(), 2); ri; ++ri) if (!cell_is_solid(*ri) && env.cgrid(*ri) == EMPTY_CLOUD && one_chance_in(20)) { place_cloud( cloud, *ri, random2(10), KC_OTHER, 1); } } static void _RCLOUDS_equip(item_def *item, bool *show_msgs, bool unmeld) { _equip_mpr(show_msgs, "A thin mist springs up around you!"); }