From 5f1ddaaadb3153c9e4dcbc091fb34831118d30ba Mon Sep 17 00:00:00 2001 From: Neil Moore Date: Wed, 25 Nov 2015 14:44:48 -0500 Subject: [PATCH] Begin data-ifying passive divine abilities [WIP] Add a new layer representing passive divine abilities, rather than checking directly for specific gods and piety levels. The idea is to decouple abilities from specific gods, allowing the same abilities to be used for randgods. Ashenzari, Beogh, Cheibriados, and Dithmenos have been converted so far. --- crawl-ref/source/abyss.cc | 3 +- crawl-ref/source/acquire.cc | 3 +- crawl-ref/source/areas.cc | 7 +- crawl-ref/source/art-func.h | 3 +- crawl-ref/source/attack.cc | 3 +- crawl-ref/source/attitude-change.cc | 5 +- crawl-ref/source/beam.cc | 3 +- crawl-ref/source/decks.cc | 11 +- crawl-ref/source/fight.cc | 3 +- crawl-ref/source/godabil.cc | 220 -------------- crawl-ref/source/godabil.h | 7 - crawl-ref/source/godpassive.cc | 430 +++++++++++++++++++++++++++- crawl-ref/source/godpassive.h | 97 +++++++ crawl-ref/source/godwrath.cc | 1 + crawl-ref/source/invent.cc | 3 +- crawl-ref/source/item_use.cc | 3 +- crawl-ref/source/itemname.cc | 9 +- crawl-ref/source/itemprop.cc | 10 +- crawl-ref/source/main.cc | 2 +- crawl-ref/source/map_knowledge.cc | 8 +- crawl-ref/source/melee_attack.cc | 3 +- crawl-ref/source/mon-cast.cc | 2 +- crawl-ref/source/mon-death.cc | 9 +- crawl-ref/source/mon-place.cc | 6 +- crawl-ref/source/mon-transit.cc | 3 +- crawl-ref/source/mutation.cc | 5 +- crawl-ref/source/orb.cc | 5 +- crawl-ref/source/ouch.cc | 11 +- crawl-ref/source/output.cc | 2 +- crawl-ref/source/player-act.cc | 11 +- crawl-ref/source/player-reacts.cc | 4 +- crawl-ref/source/player.cc | 32 +-- crawl-ref/source/religion.cc | 111 ++++--- crawl-ref/source/skill_menu.cc | 12 +- crawl-ref/source/spl-cast.cc | 5 +- crawl-ref/source/spl-goditem.cc | 4 +- crawl-ref/source/stairs.cc | 8 +- crawl-ref/source/stash.cc | 2 +- crawl-ref/source/terrain.cc | 3 +- crawl-ref/source/throw.cc | 3 +- crawl-ref/source/timed_effects.cc | 6 +- crawl-ref/source/transform.cc | 7 +- crawl-ref/source/traps.cc | 3 +- crawl-ref/source/wiz-item.cc | 2 +- 44 files changed, 716 insertions(+), 374 deletions(-) diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc index 4311093e9c3..531f06b99a3 100644 --- a/crawl-ref/source/abyss.cc +++ b/crawl-ref/source/abyss.cc @@ -24,6 +24,7 @@ #include "dgn-overview.h" #include "dgn-proclayouts.h" #include "files.h" +#include "godpassive.h" // passive_t::slow_abyss #include "hiscores.h" #include "itemprop.h" #include "items.h" @@ -1592,7 +1593,7 @@ void generate_abyss() static void _increase_depth() { int delta = you.time_taken * (you.abyss_speed + 40) / 200; - if (!you_worship(GOD_CHEIBRIADOS) || you.penance[GOD_CHEIBRIADOS]) + if (!have_passive(passive_t::slow_abyss)) delta *= 2; if (you.duration[DUR_TELEPORT]) delta *= 5; diff --git a/crawl-ref/source/acquire.cc b/crawl-ref/source/acquire.cc index 5b618d92eb3..71a10fd1a43 100644 --- a/crawl-ref/source/acquire.cc +++ b/crawl-ref/source/acquire.cc @@ -21,6 +21,7 @@ #include "dungeon.h" #include "food.h" #include "goditem.h" +#include "godpassive.h" #include "itemname.h" #include "itemprop.h" #include "items.h" @@ -1423,7 +1424,7 @@ int acquirement_create_item(object_class_type class_wanted, acq_item.quantity = quant; // Remove curse flag from item, unless worshipping Ashenzari. - if (you_worship(GOD_ASHENZARI)) + if (have_passive(passive_t::want_curses)) do_curse_item(acq_item, true); else do_uncurse_item(acq_item, false); diff --git a/crawl-ref/source/areas.cc b/crawl-ref/source/areas.cc index b2633ff5574..58053e54b85 100644 --- a/crawl-ref/source/areas.cc +++ b/crawl-ref/source/areas.cc @@ -16,6 +16,7 @@ #include "env.h" #include "fprop.h" #include "godconduct.h" +#include "godpassive.h" // passive_t::umbra #include "libutil.h" #include "losglobal.h" #include "message.h" @@ -710,11 +711,11 @@ int player::umbra_radius() const { int size = -1; - if (religion == GOD_DITHMENOS && piety >= piety_breakpoint(0) - && !penance[GOD_DITHMENOS]) + if (have_passive(passive_t::umbra)) { // The cap is reached at piety 160 = ******. - size = min((int)piety, piety_breakpoint(5)) * LOS_RADIUS / piety_breakpoint(5); + size = min((int)piety, piety_breakpoint(5)) * LOS_RADIUS + / piety_breakpoint(5); } if (player_equip_unrand(UNRAND_SHADOWS)) diff --git a/crawl-ref/source/art-func.h b/crawl-ref/source/art-func.h index 658ec0d3907..ea2e6fd7554 100644 --- a/crawl-ref/source/art-func.h +++ b/crawl-ref/source/art-func.h @@ -28,6 +28,7 @@ #include "food.h" // For evokes #include "ghost.h" // For is_dragonkind ghost_demon datas #include "godconduct.h" // did_god_conduct +#include "godpassive.h" // passive_t::want_curses #include "mgen_data.h" // For Sceptre of Asmodeus evoke #include "mon-death.h" // For demon axe's SAME_ATTITUDE #include "mon-place.h" // For Sceptre of Asmodeus evoke @@ -171,7 +172,7 @@ static void _CURSES_equip(item_def *item, bool *show_msgs, bool unmeld) static void _CURSES_world_reacts(item_def *item) { // don't spam messages for ash worshippers - if (one_chance_in(30) && !you_worship(GOD_ASHENZARI)) + if (one_chance_in(30) && !have_passive(passive_t::want_curses)) curse_an_item(true); } diff --git a/crawl-ref/source/attack.cc b/crawl-ref/source/attack.cc index e4844c965d4..5ff1444ca47 100644 --- a/crawl-ref/source/attack.cc +++ b/crawl-ref/source/attack.cc @@ -22,6 +22,7 @@ #include "fight.h" #include "fineff.h" #include "godconduct.h" +#include "godpassive.h" // passive_t::no_haste #include "itemname.h" #include "itemprop.h" #include "message.h" @@ -749,7 +750,7 @@ void attack::chaos_affects_defender() beam.flavour = BEAM_HEALING; break; case CHAOS_HASTE: - if (defender->is_player() && you_worship(GOD_CHEIBRIADOS)) + if (defender->is_player() && have_passive(passive_t::no_haste)) { simple_god_message(" protects you from inadvertent hurry."); obvious_effect = true; diff --git a/crawl-ref/source/attitude-change.cc b/crawl-ref/source/attitude-change.cc index 0cb6f196115..76bf513dfac 100644 --- a/crawl-ref/source/attitude-change.cc +++ b/crawl-ref/source/attitude-change.cc @@ -16,6 +16,7 @@ #include "env.h" #include "godabil.h" #include "godcompanions.h" +#include "godpassive.h" // passive_t::convert_orcs #include "libutil.h" #include "message.h" #include "mon-behv.h" @@ -72,7 +73,7 @@ void beogh_follower_convert(monster* mons, bool orc_hit) return; // For followers of Beogh, decide whether orcs will join you. - if (you_worship(GOD_BEOGH) + if (will_have_passive(passive_t::convert_orcs) && mons->foe == MHITYOU && mons_genus(mons->type) == MONS_ORC && !mons->is_summoned() @@ -86,7 +87,7 @@ void beogh_follower_convert(monster* mons, bool orc_hit) const int hd = mons->get_experience_level(); - if (in_good_standing(GOD_BEOGH, 2) + if (have_passive(passive_t::convert_orcs) && random2(you.piety / 15) + random2(4 + you.experience_level / 3) > random2(hd) + hd + random2(5)) { diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index 449933e9e5d..515873f9e61 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -32,6 +32,7 @@ #include "fight.h" #include "godabil.h" #include "godconduct.h" +#include "godpassive.h" // passive_t::convert_orcs #include "item_use.h" #include "itemprop.h" #include "items.h" @@ -4373,7 +4374,7 @@ void bolt::enchantment_affect_monster(monster* mon) set_attack_conducts(conducts, mon, you.can_see(*mon)); - if (in_good_standing(GOD_BEOGH, 2) + if (have_passive(passive_t::convert_orcs) && mons_genus(mon->type) == MONS_ORC && mon->asleep() && mons_near(mon)) { diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc index acfa7bd407c..f987a7d6f2f 100644 --- a/crawl-ref/source/decks.cc +++ b/crawl-ref/source/decks.cc @@ -25,6 +25,7 @@ #include "evoke.h" #include "food.h" #include "ghost.h" +#include "godpassive.h" // passive_t::no_haste #include "godwrath.h" #include "invent.h" #include "itemprop.h" @@ -1418,7 +1419,7 @@ static void _velocity_card(int power, deck_rarity_type rarity) if (you.duration[DUR_SLOW] && (power_level > 0 || coinflip())) { - if (you_worship(GOD_CHEIBRIADOS)) + if (have_passive(passive_t::no_haste)) simple_god_message(" protects you from inadvertent hurry."); else { @@ -1476,7 +1477,7 @@ static void _velocity_card(int power, deck_rarity_type rarity) } else if (!(for_hostiles == ENCH_HASTE && haste_immune)) { - if (you_worship(GOD_CHEIBRIADOS)) + if (have_passive(passive_t::no_haste)) _suppressed_card_message(you.religion, DID_HASTY); else { @@ -1501,7 +1502,7 @@ static void _velocity_card(int power, deck_rarity_type rarity) } else if (!(for_allies == ENCH_HASTE && haste_immune)) { - if (you_worship(GOD_CHEIBRIADOS)) + if (have_passive(passive_t::no_haste)) _suppressed_card_message(you.religion, DID_HASTY); else { @@ -2010,8 +2011,8 @@ static void _potion_card(int power, deck_rarity_type rarity) if (power_level >= 2 && coinflip()) pot = (coinflip() ? POT_HEAL_WOUNDS : POT_MAGIC); - if (you_worship(GOD_CHEIBRIADOS) && (pot == POT_HASTE - || pot == POT_BERSERK_RAGE)) + if (have_passive(passive_t::no_haste) + && (pot == POT_HASTE || pot == POT_BERSERK_RAGE)) { simple_god_message(" protects you from inadvertent hurry."); return; diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index ecff9fb9c2b..15e6c365a19 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -20,6 +20,7 @@ #include "fineff.h" #include "fprop.h" #include "godabil.h" +#include "godpassive.h" // passive_t::shadow_attacks #include "hints.h" #include "invent.h" #include "itemprop.h" @@ -174,7 +175,7 @@ bool fight_melee(actor *attacker, actor *defender, bool *did_hit, bool simu) if (!simu && you.props.exists("spectral_weapon")) trigger_spectral_weapon(&you, defender); - if (!simu && you_worship(GOD_DITHMENOS)) + if (!simu && will_have_passive(passive_t::shadow_attacks)) dithmenos_shadow_melee(defender); return true; diff --git a/crawl-ref/source/godabil.cc b/crawl-ref/source/godabil.cc index ea19121ee5c..9fc4a9770d4 100644 --- a/crawl-ref/source/godabil.cc +++ b/crawl-ref/source/godabil.cc @@ -27,7 +27,6 @@ #include "directn.h" #include "dungeon.h" #include "english.h" -#include "fight.h" #include "files.h" #include "food.h" #include "godblessing.h" @@ -48,7 +47,6 @@ #include "mon-act.h" #include "mon-behv.h" #include "mon-book.h" -#include "mon-cast.h" #include "mon-death.h" #include "mon-place.h" #include "mon-poly.h" @@ -78,7 +76,6 @@ #include "target.h" #include "teleport.h" // monster_teleport #include "terrain.h" -#include "throw.h" #ifdef USE_TILE #include "tiledef-main.h" #endif @@ -1613,11 +1610,6 @@ void trog_remove_trogs_hand() you.duration[DUR_TROGS_HAND] = 0; } -bool beogh_water_walk() -{ - return in_good_standing(GOD_BEOGH, 4); -} - /** * Has the monster been given a Beogh gift? * @@ -3958,218 +3950,6 @@ bool dithmenos_shadow_step() return true; } -static bool _dithmenos_shadow_acts() -{ - if (!in_good_standing(GOD_DITHMENOS, 3)) - return false; - - // 10% chance at 4* piety; 50% chance at 200 piety. - const int range = MAX_PIETY - piety_breakpoint(3); - const int min = range / 5; - return x_chance_in_y(min + ((range - min) - * (you.piety - piety_breakpoint(3)) - / (MAX_PIETY - piety_breakpoint(3))), - 2 * range); -} - -monster* shadow_monster(bool equip) -{ - if (monster_at(you.pos())) - return nullptr; - - int wpn_index = NON_ITEM; - - // Do a basic clone of the weapon. - item_def* wpn = you.weapon(); - if (equip - && wpn - && (wpn->base_type == OBJ_WEAPONS - || wpn->base_type == OBJ_STAVES - || wpn->base_type == OBJ_RODS)) - { - wpn_index = get_mitm_slot(10); - if (wpn_index == NON_ITEM) - return nullptr; - item_def& new_item = mitm[wpn_index]; - if (wpn->base_type == OBJ_STAVES) - { - new_item.base_type = OBJ_WEAPONS; - new_item.sub_type = WPN_STAFF; - } - else if (wpn->base_type == OBJ_RODS) - { - new_item.base_type = OBJ_WEAPONS; - new_item.sub_type = WPN_ROD; - } - else - { - new_item.base_type = wpn->base_type; - new_item.sub_type = wpn->sub_type; - } - new_item.quantity = 1; - new_item.rnd = 1; - new_item.flags |= ISFLAG_SUMMONED; - } - - monster* mon = get_free_monster(); - if (!mon) - { - if (wpn_index) - destroy_item(wpn_index); - return nullptr; - } - - mon->type = MONS_PLAYER_SHADOW; - mon->behaviour = BEH_SEEK; - mon->attitude = ATT_FRIENDLY; - mon->flags = MF_NO_REWARD | MF_JUST_SUMMONED | MF_SEEN - | MF_WAS_IN_VIEW | MF_HARD_RESET; - mon->hit_points = you.hp; - mon->set_hit_dice(min(27, max(1, - you.skill_rdiv(wpn_index != NON_ITEM - ? item_attack_skill(mitm[wpn_index]) - : SK_UNARMED_COMBAT, 10, 20) - + you.skill_rdiv(SK_FIGHTING, 10, 20)))); - mon->set_position(you.pos()); - mon->mid = MID_PLAYER; - mon->inv[MSLOT_WEAPON] = wpn_index; - mon->inv[MSLOT_MISSILE] = NON_ITEM; - - mgrd(you.pos()) = mon->mindex(); - - return mon; -} - -void shadow_monster_reset(monster *mon) -{ - if (mon->inv[MSLOT_WEAPON] != NON_ITEM) - destroy_item(mon->inv[MSLOT_WEAPON]); - if (mon->inv[MSLOT_MISSILE] != NON_ITEM) - destroy_item(mon->inv[MSLOT_MISSILE]); - - mon->reset(); -} - -/** - * Check if the player is in melee range of the target. - * - * Certain effects, e.g. distortion blink, can cause monsters to leave melee - * range between the initial hit & the shadow mimic. - * - * XXX: refactor this with attack/fight code! - * - * @param target The creature to be struck. - * @return Whether the player is melee range of the target, using - * their current weapon. - */ -static bool _in_melee_range(actor* target) -{ - const int dist = (you.pos() - target->pos()).abs(); - return dist < 2 || (dist <= 2 && you.reach_range() != REACH_NONE); -} - -void dithmenos_shadow_melee(actor* target) -{ - if (!target - || !target->alive() - || !_in_melee_range(target) - || !_dithmenos_shadow_acts()) - { - return; - } - - monster* mon = shadow_monster(); - if (!mon) - return; - - mon->target = target->pos(); - mon->foe = target->mindex(); - - fight_melee(mon, target); - - shadow_monster_reset(mon); -} - -void dithmenos_shadow_throw(const dist &d, const item_def &item) -{ - ASSERT(d.isValid); - if (!_dithmenos_shadow_acts()) - return; - - monster* mon = shadow_monster(); - if (!mon) - return; - - int ammo_index = get_mitm_slot(10); - if (ammo_index != NON_ITEM) - { - item_def& new_item = mitm[ammo_index]; - new_item.base_type = item.base_type; - new_item.sub_type = item.sub_type; - new_item.quantity = 1; - new_item.rnd = 1; - new_item.flags |= ISFLAG_SUMMONED; - mon->inv[MSLOT_MISSILE] = ammo_index; - - mon->target = clamp_in_bounds(d.target); - - bolt beem; - beem.set_target(d); - setup_monster_throw_beam(mon, beem); - beem.item = &mitm[mon->inv[MSLOT_MISSILE]]; - mons_throw(mon, beem, mon->inv[MSLOT_MISSILE]); - } - - shadow_monster_reset(mon); -} - -void dithmenos_shadow_spell(bolt* orig_beam, spell_type spell) -{ - if (!orig_beam) - return; - - const coord_def target = orig_beam->target; - - if (orig_beam->target.origin() - || (orig_beam->is_enchantment() && !is_valid_mon_spell(spell)) - || orig_beam->flavour == BEAM_ENSLAVE - && monster_at(target) && monster_at(target)->friendly() - || !_dithmenos_shadow_acts()) - { - return; - } - - monster* mon = shadow_monster(); - if (!mon) - return; - - // Don't let shadow spells get too powerful. - mon->set_hit_dice(max(1, - min(3 * spell_difficulty(spell), - you.experience_level) / 2)); - - mon->target = clamp_in_bounds(target); - if (actor_at(target)) - mon->foe = actor_at(target)->mindex(); - - spell_type shadow_spell = spell; - if (!orig_beam->is_enchantment()) - { - shadow_spell = (orig_beam->pierce) ? SPELL_SHADOW_BOLT - : SPELL_SHADOW_SHARD; - } - - bolt beem; - beem.target = target; - beem.aimed_at_spot = orig_beam->aimed_at_spot; - - mprf(MSGCH_FRIEND_SPELL, "%s mimicks your spell!", - mon->name(DESC_THE).c_str()); - mons_cast(mon, beem, shadow_spell, MON_SPELL_WIZARD, false); - - shadow_monster_reset(mon); -} - static potion_type _gozag_potion_list[][4] = { { POT_HEAL_WOUNDS, NUM_POTIONS, NUM_POTIONS, NUM_POTIONS }, diff --git a/crawl-ref/source/godabil.h b/crawl-ref/source/godabil.h index 17d7ff639d8..07aadfb109d 100644 --- a/crawl-ref/source/godabil.h +++ b/crawl-ref/source/godabil.h @@ -43,7 +43,6 @@ const char * const GOZAG_SHOP_COST_KEY = "gozag_shop_cost_%d"; struct bolt; class stack_iterator; -class dist; bool can_do_capstone_ability(god_type god); bool bless_weapon(god_type god, brand_type brand, colour_t colour); @@ -75,7 +74,6 @@ void trog_remove_trogs_hand(); void jiyva_paralyse_jellies(); bool jiyva_remove_bad_mutation(); -bool beogh_water_walk(); bool beogh_can_gift_items_to(const monster* mons, bool quiet = true); bool beogh_gift_item(); @@ -126,11 +124,6 @@ bool can_convert_to_beogh(); void spare_beogh_convert(); bool dithmenos_shadow_step(); -monster* shadow_monster(bool equip = true); -void shadow_monster_reset(monster *mon); -void dithmenos_shadow_melee(actor* target); -void dithmenos_shadow_throw(const dist &d, const item_def &item); -void dithmenos_shadow_spell(bolt* orig_beam, spell_type spell); int gozag_potion_price(); bool gozag_setup_potion_petition(bool quiet = false); diff --git a/crawl-ref/source/godpassive.cc b/crawl-ref/source/godpassive.cc index 69036d791fb..4f76ee85e5f 100644 --- a/crawl-ref/source/godpassive.cc +++ b/crawl-ref/source/godpassive.cc @@ -2,6 +2,7 @@ #include "godpassive.h" +#include #include #include "artefact.h" @@ -9,7 +10,9 @@ #include "branch.h" #include "cloud.h" #include "coordit.h" +#include "directn.h" #include "env.h" +#include "fight.h" #include "files.h" #include "food.h" #include "fprop.h" @@ -21,16 +24,208 @@ #include "items.h" #include "libutil.h" #include "message.h" +#include "mon-cast.h" +#include "mon-place.h" #include "religion.h" #include "shout.h" #include "skills.h" #include "state.h" #include "stringutil.h" #include "terrain.h" +#include "throw.h" + +// TODO: template out the differences between this and god_power. +struct god_passive +{ + // 1-6 means it unlocks at that many stars of piety; + // 0 means it is always present when in good standing with the god; + // -1 means it is present even under penance; + int rank; + passive_t pasv; + const char* gain; + const char* loss; + + god_passive(int rank_, passive_t pasv_, const char* gain_, + const char* loss_ = "") + : rank{rank_}, pasv{pasv_}, gain{gain_}, loss{*loss_ ? loss_ : gain_} + { } + + god_passive(int rank_, const char* gain_, const char* loss_ = "") + : god_passive(rank_, passive_t::none, gain_, loss_) + { } + + void display(bool gaining, const char* fmt) const + { + const char * const str = gaining ? gain : loss; + if (isupper(str[0])) + god_speaks(you.religion, str); + else + god_speaks(you.religion, make_stringf(fmt, str).c_str()); + } +}; + +static const vector god_passives[NUM_GODS] = +{ + // no god + { }, + + // Zin + { }, + + // TSO + { }, + + // Kikubaaqudgha + { }, + + // Yredelemnul + { + { 3, passive_t::nightvision, "can see well in the dark" }, + }, + + // Xom + { }, + + // Vehumet + { }, + + // Okawaru + { }, + + // Makhleb + { }, + + // Sif Muna + { }, + + // Trog + { }, + + // Nemelex + { }, + + // Elyvilon + { }, + + // Lugonu + { }, + + // Beogh + { + { -1, passive_t::share_exp, "share experience with your followers" }, + { 0, passive_t::bonus_ac, "gain increased benefits from armour" }, + { 3, passive_t::convert_orcs, "inspire orcs to join your side" }, + { 3, passive_t::bless_followers, + "GOD will bless your followers.", + "GOD will no longer bless your followers." + }, + { 5, passive_t::water_walk, "walk on water" }, + }, + + // Jiyva + { }, + + // Fedhas + { }, + + // Cheibriados + { + { -1, passive_t::no_haste, "are protected from inadvertent hurry" }, + { -1, passive_t::slowed, "move less quickly" }, + { 0, passive_t::slow_orb_run, + "GOD will aid your escape with the Orb of Zot.", + "GOD will no longer aid your escape with the Orb of Zot." + }, + { 0, passive_t::stat_boost, + "GOD supports your attributes", + "GOD no longer supports your attributes", + }, + { 0, passive_t::slow_abyss, + "GOD will slow the abyss.", + "GOD will no longer slow the abyss." + }, + // TODO: this one should work regardless of penance + { 1, passive_t::slow_metabolism, "have a slowed metabolism" }, + }, + + // Ashenzari + { + { -1, passive_t::want_curses, "prefer cursed items" }, + { -1, passive_t::detect_portals, "sense portals" }, + { -1, passive_t::identify_items, "sense the properties of items" }, + { 0, passive_t::auto_map, "have improved mapping abilities" }, + { 0, passive_t::detect_montier, "sense threats" }, + { 0, passive_t::detect_items, "sense items" }, + { 0, passive_t::search_traps, "are better at searching for traps" }, + { 2, passive_t::bondage_skill_boost, + "get a skill boost from cursed items" }, + { 3, passive_t::sinv, "are clear of vision" }, + { 4, passive_t::clarity, "are clear of mind" }, + }, + + // Dithmenos + { + { 1, passive_t::nightvision, "can see well in the dark" }, + { 1, passive_t::umbra, "are surrounded by an umbra" }, + // TODO: this one should work regardless of penance. + { 3, passive_t::hit_smoke, "emit smoke when hit" }, + { 4, passive_t::shadow_attacks, + "Your attacks are mimicked by a shadow.", + "Your attacks are no longer mimicked by a shadow." + }, + { 4, passive_t::shadow_spells, + "Your attack spells are mimicked by a shadow.", + "Your attack spells are no longer mimicked by a shadow." + }, + }, + + // Gozag + { }, + + // Qazlal + { }, + + // Ru + { }, +}; + +bool have_passive(passive_t passive) +{ + const auto &pasvec = god_passives[you.religion]; + return any_of(begin(pasvec), end(pasvec), + [passive] (const god_passive &p) -> bool + { + return p.pasv == passive + && piety_rank() >= p.rank + && (!player_under_penance() || p.rank < 0); + }); +} + +bool will_have_passive(passive_t passive) +{ + const auto &pasvec = god_passives[you.religion]; + return any_of(begin(pasvec), end(pasvec), + [passive] (const god_passive &p) -> bool + { + return p.pasv == passive; + }); +} + +// Returns a large number (10) if we will never get this passive. +int rank_for_passive(passive_t passive) +{ + const auto &pasvec = god_passives[you.religion]; + const auto found = find_if(begin(pasvec), end(pasvec), + [passive] (const god_passive &p) -> bool + { + return p.pasv == passive; + }); + return found == end(pasvec) ? 10 : found->rank; +} int chei_stat_boost(int piety) { - if (!you_worship(GOD_CHEIBRIADOS) || you.penance[GOD_CHEIBRIADOS]) + if (!have_passive(passive_t::stat_boost)) return 0; if (piety < piety_breakpoint(0)) // Since you've already begun to slow down. return 1; @@ -169,7 +364,7 @@ static bool _two_handed() void ash_check_bondage(bool msg) { - if (!you_worship(GOD_ASHENZARI)) + if (!will_have_passive(passive_t::bondage_skill_boost)) return; int cursed[NUM_ET] = {0}, slots[NUM_ET] = {0}; @@ -398,8 +593,12 @@ bool god_id_item(item_def& item, bool silent) iflags_t old_ided = item.flags & ISFLAG_IDENT_MASK; iflags_t ided = 0; - if (you_worship(GOD_ASHENZARI)) + if (have_passive(passive_t::identify_items)) { + // Ashenzari (and other gods with both identify_items and want_curses) + // ties identification of weapon/armour plusses to cursed slots. + const bool ash = have_passive(passive_t::want_curses); + // Don't identify runes or the orb, since this has no gameplay purpose // and might mess up other things. if (item.base_type == OBJ_RUNES || item_is_orb(item)) @@ -420,13 +619,13 @@ bool god_id_item(item_def& item, bool silent) ided |= ISFLAG_IDENT_MASK; if (item.base_type == OBJ_ARMOUR - && _is_slot_cursed(get_armour_slot(item))) + && (!ash || _is_slot_cursed(get_armour_slot(item)))) { ided |= ISFLAG_KNOW_PLUSES; } if (is_weapon(item) - && _is_slot_cursed(EQ_WEAPON)) + && (!ash || _is_slot_cursed(EQ_WEAPON))) { ided |= ISFLAG_KNOW_PLUSES; } @@ -459,7 +658,7 @@ bool god_id_item(item_def& item, bool silent) void ash_id_monster_equipment(monster* mon) { - if (!you_worship(GOD_ASHENZARI)) + if (!have_passive(passive_t::identify_items)) return; bool id = false; @@ -537,7 +736,7 @@ static bool _check_portal(coord_def where) int ash_detect_portals(bool all) { - if (!you_worship(GOD_ASHENZARI)) + if (!have_passive(passive_t::detect_portals)) return 0; int portals_found = 0; @@ -880,3 +1079,220 @@ ru_interference get_ru_attack_interference_level() else return DO_NOTHING; } + +static bool _shadow_acts(bool spell) +{ + const passive_t pasv = spell ? passive_t::shadow_spells + : passive_t::shadow_attacks; + if (!have_passive(pasv)) + return false; + + const int minpiety = piety_breakpoint(rank_for_passive(pasv) - 1); + + // 10% chance at minimum piety; 50% chance at 200 piety. + const int range = MAX_PIETY - minpiety; + const int min = range / 5; + return x_chance_in_y(min + ((range - min) + * (you.piety - minpiety) + / (MAX_PIETY - minpiety)), + 2 * range); +} + +monster* shadow_monster(bool equip) +{ + if (monster_at(you.pos())) + return nullptr; + + int wpn_index = NON_ITEM; + + // Do a basic clone of the weapon. + item_def* wpn = you.weapon(); + if (equip + && wpn + && (wpn->base_type == OBJ_WEAPONS + || wpn->base_type == OBJ_STAVES + || wpn->base_type == OBJ_RODS)) + { + wpn_index = get_mitm_slot(10); + if (wpn_index == NON_ITEM) + return nullptr; + item_def& new_item = mitm[wpn_index]; + if (wpn->base_type == OBJ_STAVES) + { + new_item.base_type = OBJ_WEAPONS; + new_item.sub_type = WPN_STAFF; + } + else if (wpn->base_type == OBJ_RODS) + { + new_item.base_type = OBJ_WEAPONS; + new_item.sub_type = WPN_ROD; + } + else + { + new_item.base_type = wpn->base_type; + new_item.sub_type = wpn->sub_type; + } + new_item.quantity = 1; + new_item.rnd = 1; + new_item.flags |= ISFLAG_SUMMONED; + } + + monster* mon = get_free_monster(); + if (!mon) + { + if (wpn_index) + destroy_item(wpn_index); + return nullptr; + } + + mon->type = MONS_PLAYER_SHADOW; + mon->behaviour = BEH_SEEK; + mon->attitude = ATT_FRIENDLY; + mon->flags = MF_NO_REWARD | MF_JUST_SUMMONED | MF_SEEN + | MF_WAS_IN_VIEW | MF_HARD_RESET; + mon->hit_points = you.hp; + mon->set_hit_dice(min(27, max(1, + you.skill_rdiv(wpn_index != NON_ITEM + ? item_attack_skill(mitm[wpn_index]) + : SK_UNARMED_COMBAT, 10, 20) + + you.skill_rdiv(SK_FIGHTING, 10, 20)))); + mon->set_position(you.pos()); + mon->mid = MID_PLAYER; + mon->inv[MSLOT_WEAPON] = wpn_index; + mon->inv[MSLOT_MISSILE] = NON_ITEM; + + mgrd(you.pos()) = mon->mindex(); + + return mon; +} + +void shadow_monster_reset(monster *mon) +{ + if (mon->inv[MSLOT_WEAPON] != NON_ITEM) + destroy_item(mon->inv[MSLOT_WEAPON]); + if (mon->inv[MSLOT_MISSILE] != NON_ITEM) + destroy_item(mon->inv[MSLOT_MISSILE]); + + mon->reset(); +} + +/** + * Check if the player is in melee range of the target. + * + * Certain effects, e.g. distortion blink, can cause monsters to leave melee + * range between the initial hit & the shadow mimic. + * + * XXX: refactor this with attack/fight code! + * + * @param target The creature to be struck. + * @return Whether the player is melee range of the target, using + * their current weapon. + */ +static bool _in_melee_range(actor* target) +{ + const int dist = (you.pos() - target->pos()).abs(); + return dist < 2 || (dist <= 2 && you.reach_range() != REACH_NONE); +} + +void dithmenos_shadow_melee(actor* target) +{ + if (!target + || !target->alive() + || !_in_melee_range(target) + || !_shadow_acts(false)) + { + return; + } + + monster* mon = shadow_monster(); + if (!mon) + return; + + mon->target = target->pos(); + mon->foe = target->mindex(); + + fight_melee(mon, target); + + shadow_monster_reset(mon); +} + +void dithmenos_shadow_throw(const dist &d, const item_def &item) +{ + ASSERT(d.isValid); + if (!_shadow_acts(false)) + return; + + monster* mon = shadow_monster(); + if (!mon) + return; + + int ammo_index = get_mitm_slot(10); + if (ammo_index != NON_ITEM) + { + item_def& new_item = mitm[ammo_index]; + new_item.base_type = item.base_type; + new_item.sub_type = item.sub_type; + new_item.quantity = 1; + new_item.rnd = 1; + new_item.flags |= ISFLAG_SUMMONED; + mon->inv[MSLOT_MISSILE] = ammo_index; + + mon->target = clamp_in_bounds(d.target); + + bolt beem; + beem.set_target(d); + setup_monster_throw_beam(mon, beem); + beem.item = &mitm[mon->inv[MSLOT_MISSILE]]; + mons_throw(mon, beem, mon->inv[MSLOT_MISSILE]); + } + + shadow_monster_reset(mon); +} + +void dithmenos_shadow_spell(bolt* orig_beam, spell_type spell) +{ + if (!orig_beam) + return; + + const coord_def target = orig_beam->target; + + if (orig_beam->target.origin() + || (orig_beam->is_enchantment() && !is_valid_mon_spell(spell)) + || orig_beam->flavour == BEAM_ENSLAVE + && monster_at(target) && monster_at(target)->friendly() + || !_shadow_acts(true)) + { + return; + } + + monster* mon = shadow_monster(); + if (!mon) + return; + + // Don't let shadow spells get too powerful. + mon->set_hit_dice(max(1, + min(3 * spell_difficulty(spell), + you.experience_level) / 2)); + + mon->target = clamp_in_bounds(target); + if (actor_at(target)) + mon->foe = actor_at(target)->mindex(); + + spell_type shadow_spell = spell; + if (!orig_beam->is_enchantment()) + { + shadow_spell = (orig_beam->pierce) ? SPELL_SHADOW_BOLT + : SPELL_SHADOW_SHARD; + } + + bolt beem; + beem.target = target; + beem.aimed_at_spot = orig_beam->aimed_at_spot; + + mprf(MSGCH_FRIEND_SPELL, "%s mimicks your spell!", + mon->name(DESC_THE).c_str()); + mons_cast(mon, beem, shadow_spell, MON_SPELL_WIZARD, false); + + shadow_monster_reset(mon); +} + diff --git a/crawl-ref/source/godpassive.h b/crawl-ref/source/godpassive.h index bdc342ac751..9262fe84ee8 100644 --- a/crawl-ref/source/godpassive.h +++ b/crawl-ref/source/godpassive.h @@ -10,6 +10,94 @@ #include "player.h" class monster; +class dist; + +// Passive god abilities. +enum class passive_t +{ + /// Placeholder for absence of a passive ability. + none = 0, + + /// The god prefers that items be cursed: acquirement grants cursed items, + /// enchant scrolls and miscasts preserve curse status, and remove curse + /// allows selecting a subset of items. + want_curses, + + /// You detect the presence of portals. + detect_portals, + + /// You identity items on sight, including monster equipment. + identify_items, + + /// You have (improved) automatic mapping. + auto_map, + + /// You detect the threat level of monsters. + detect_montier, + + /// You detect the presence of items. + detect_items, + + /// You are better at searching for traps. + search_traps, + + /// You have innate see invisible. + sinv, + + /// You have innate clarity. + clarity, + + /// You get a boost to skills from cursed slots. + bondage_skill_boost, + + /// You convert orcs into followers. + convert_orcs, + + /// You can walk on water. + water_walk, + + /// You share experience with followers. + share_exp, + + /// Your god blesses your followers. + bless_followers, + + /// You receive a bonus to armour class. + bonus_ac, + + /// You cannot be hasted. + no_haste, + + /// You move slowly. + slowed, + + /// Fewer creatures spawn on the orb run. + slow_orb_run, + + /// Fewer creatures spawn in the Abyss, and it morphs less quickly. + slow_abyss, + + /// Your attributes are boosted. + stat_boost, + + /// Hunger, poison, and disease affect you more slowly. + slow_metabolism, + + /// You have an umbra. + umbra, + + /// You emit clouds when hit. + hit_smoke, + + /// Your shadow attacks alongside you. + shadow_attacks, + + /// Your shadow casts attack spells alongside you. + shadow_spells, + + /// You see better in the dark. + nightvision, +}; enum jiyva_slurp_results { @@ -26,6 +114,9 @@ enum ru_interference DO_REDIRECT_ATTACK }; +bool have_passive(passive_t passive); +bool will_have_passive(passive_t passive); +int rank_for_passive(passive_t passive); int chei_stat_boost(int piety = you.piety); void jiyva_eat_offlevel_items(); void jiyva_slurp_bonus(int item_value, int *js); @@ -46,4 +137,10 @@ void qazlal_storm_clouds(); void qazlal_element_adapt(beam_type flavour, int strength); bool does_ru_wanna_redirect(monster* mon); ru_interference get_ru_attack_interference_level(); + +monster* shadow_monster(bool equip = true); +void shadow_monster_reset(monster *mon); +void dithmenos_shadow_melee(actor* target); +void dithmenos_shadow_throw(const dist &d, const item_def &item); +void dithmenos_shadow_spell(bolt* orig_beam, spell_type spell); #endif diff --git a/crawl-ref/source/godwrath.cc b/crawl-ref/source/godwrath.cc index d32800c37a9..36c51b08384 100644 --- a/crawl-ref/source/godwrath.cc +++ b/crawl-ref/source/godwrath.cc @@ -19,6 +19,7 @@ #include "food.h" #include "ghost.h" #include "godabil.h" +#include "godpassive.h" // shadow_monster #include "itemprop.h" #include "items.h" #include "makeitem.h" diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc index d03c814714d..0f343677bf0 100644 --- a/crawl-ref/source/invent.cc +++ b/crawl-ref/source/invent.cc @@ -22,6 +22,7 @@ #include "env.h" #include "food.h" #include "goditem.h" +#include "godpassive.h" #include "initfile.h" #include "itemprop.h" #include "items.h" @@ -1058,7 +1059,7 @@ bool is_item_selected(const item_def &i, int selector) return false; if ((!item_ident(i, ISFLAG_KNOW_CURSE) || item_known_cursed(i)) // Ashenzari would just preserve the curse. - && !you_worship(GOD_ASHENZARI)) + && !have_passive(passive_t::want_curses)) { return true; } diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc index ebcb1dc55ce..1d9b3e6a0d7 100644 --- a/crawl-ref/source/item_use.cc +++ b/crawl-ref/source/item_use.cc @@ -28,6 +28,7 @@ #include "godabil.h" #include "godconduct.h" #include "goditem.h" +#include "godpassive.h" #include "hints.h" #include "invent.h" #include "itemprop.h" @@ -2114,7 +2115,7 @@ bool enchant_armour(int &ac_change, bool quiet, item_def &arm) canned_msg(MSG_NOTHING_HAPPENS); // That proved that it was uncursed. - if (!you_worship(GOD_ASHENZARI)) + if (!have_passive(passive_t::want_curses)) arm.flags |= ISFLAG_KNOW_CURSE; return false; diff --git a/crawl-ref/source/itemname.cc b/crawl-ref/source/itemname.cc index 9088b4d7d01..a939b7bd130 100644 --- a/crawl-ref/source/itemname.cc +++ b/crawl-ref/source/itemname.cc @@ -29,6 +29,7 @@ #include "evoke.h" #include "food.h" #include "goditem.h" +#include "godpassive.h" // passive_t::want_curses, no_haste #include "invent.h" #include "itemprop.h" #include "items.h" @@ -3186,7 +3187,8 @@ bool is_emergency_item(const item_def &item) switch (item.sub_type) { case WAND_HASTING: - return !you_worship(GOD_CHEIBRIADOS) && you.species != SP_FORMICID; + return !have_passive(passive_t::no_haste) + && you.species != SP_FORMICID; case WAND_TELEPORTATION: return you.species != SP_FORMICID; case WAND_HEAL_WOUNDS: @@ -3213,7 +3215,8 @@ bool is_emergency_item(const item_def &item) switch (item.sub_type) { case POT_HASTE: - return !you_worship(GOD_CHEIBRIADOS) && you.species != SP_FORMICID; + return !have_passive(passive_t::no_haste) + && you.species != SP_FORMICID; case POT_HEAL_WOUNDS: return you.can_device_heal(); case POT_CURING: @@ -3295,7 +3298,7 @@ bool is_bad_item(const item_def &item, bool temp) if (you.species == SP_FELID) return false; case SCR_CURSE_JEWELLERY: - return !you_worship(GOD_ASHENZARI); + return !have_passive(passive_t::want_curses); default: return false; } diff --git a/crawl-ref/source/itemprop.cc b/crawl-ref/source/itemprop.cc index 705675c1361..439bc8c2d54 100644 --- a/crawl-ref/source/itemprop.cc +++ b/crawl-ref/source/itemprop.cc @@ -737,10 +737,10 @@ bool item_known_cursed(const item_def &item) bool curse_an_item(bool ignore_holy_wrath) { // allowing these would enable mummy scumming - if (you_worship(GOD_ASHENZARI)) + if (have_passive(passive_t::want_curses)) { mprf(MSGCH_GOD, "The curse is absorbed by %s.", - god_name(GOD_ASHENZARI).c_str()); + god_name(you.religion).c_str()); return false; } @@ -867,7 +867,7 @@ void do_uncurse_item(item_def &item, bool inscribe, bool no_ash, return; } - if (no_ash && you_worship(GOD_ASHENZARI)) + if (no_ash && have_passive(passive_t::want_curses)) { simple_god_message(" preserves the curse."); return; @@ -1653,7 +1653,7 @@ bool is_enchantable_armour(const item_def &arm, bool uncurse, bool unknown) // uncursed. if (is_artefact(arm) || arm.plus >= armour_max_enchant(arm)) { - if (!uncurse || you_worship(GOD_ASHENZARI)) + if (!uncurse || have_passive(passive_t::want_curses)) return false; if (unknown && !item_ident(arm, ISFLAG_KNOW_CURSE)) return true; @@ -2998,7 +2998,7 @@ void seen_item(const item_def &item) // major hack. Deconstify should be safe here, but it's still repulsive. const_cast(item).flags |= ISFLAG_SEEN; - if (you_worship(GOD_ASHENZARI)) + if (have_passive(passive_t::identify_items)) const_cast(item).flags |= ISFLAG_KNOW_CURSE; if (item.base_type == OBJ_GOLD && !item.plus) const_cast(item).plus = (you_worship(GOD_ZIN)) ? 2 : 1; diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc index 014383693e9..48f670f02d9 100644 --- a/crawl-ref/source/main.cc +++ b/crawl-ref/source/main.cc @@ -2361,7 +2361,7 @@ static void _prep_input() if (you.seen_portals) { - ASSERT(you_worship(GOD_ASHENZARI)); + ASSERT(have_passive(passive_t::detect_portals)); if (you.seen_portals == 1) mprf(MSGCH_GOD, "You have a vision of a gate."); else diff --git a/crawl-ref/source/map_knowledge.cc b/crawl-ref/source/map_knowledge.cc index c041941e44a..15e478ce48c 100644 --- a/crawl-ref/source/map_knowledge.cc +++ b/crawl-ref/source/map_knowledge.cc @@ -5,6 +5,7 @@ #include "coordit.h" #include "directn.h" #include "env.h" +#include "godpassive.h" // passive_t::auto_map #include "notes.h" #include "religion.h" #include "terrain.h" @@ -70,9 +71,10 @@ static void _automap_from(int x, int y, int mutated) { if (mutated) { + const bool godly = have_passive(passive_t::auto_map); magic_mapping(8 * mutated, - you_worship(GOD_ASHENZARI) ? 25 + you.piety / 8 : 25, - true, you_worship(GOD_ASHENZARI), + godly ? 25 + you.piety / 8 : 25, + true, godly, true, coord_def(x,y)); } } @@ -82,7 +84,7 @@ static int _map_quality() int passive = player_mutation_level(MUT_PASSIVE_MAPPING); // the explanation of this 51 vs max_piety of 200 is left as // an exercise to the reader - if (in_good_standing(GOD_ASHENZARI)) + if (have_passive(passive_t::auto_map)) passive = max(passive, you.piety / 51); return passive; } diff --git a/crawl-ref/source/melee_attack.cc b/crawl-ref/source/melee_attack.cc index 01f09a81800..3561a60c4a2 100644 --- a/crawl-ref/source/melee_attack.cc +++ b/crawl-ref/source/melee_attack.cc @@ -27,6 +27,7 @@ #include "food.h" #include "godconduct.h" #include "goditem.h" +#include "godpassive.h" // passive_t::convert_orcs #include "hints.h" #include "itemprop.h" #include "mapdef.h" @@ -366,7 +367,7 @@ bool melee_attack::handle_phase_hit() Hints.hints_melee_counter++; // TODO: Remove this (placed here so I can get rid of player_attack) - if (in_good_standing(GOD_BEOGH, 2) + if (have_passive(passive_t::convert_orcs) && mons_genus(defender->mons_species()) == MONS_ORC && !defender->is_summoned() && !defender->as_monster()->is_shapeshifter() diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc index 641a2152a9b..559169b8276 100644 --- a/crawl-ref/source/mon-cast.cc +++ b/crawl-ref/source/mon-cast.cc @@ -1591,7 +1591,7 @@ static bool _animate_dead_okay(spell_type spell) return false; // Annoying to drag around hordes of the undead as well as the living. - if (you_worship(GOD_BEOGH)) + if (will_have_passive(passive_t::convert_orcs)) return false; return true; diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index 66385013f8e..6ed438d348a 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -32,6 +32,7 @@ #include "godblessing.h" #include "godcompanions.h" #include "godconduct.h" +#include "godpassive.h" // passive_t::bless_followers, share_exp, convert_orcs #include "hints.h" #include "hiscores.h" #include "itemname.h" @@ -251,7 +252,7 @@ static void _give_monster_experience(int experience, int killer_index) if (mon->gain_exp(experience)) { - if (!in_good_standing(GOD_BEOGH) || !one_chance_in(3)) + if (!have_passive(passive_t::bless_followers) || !one_chance_in(3)) return; // Randomly bless the follower who gained experience. @@ -343,7 +344,7 @@ static void _give_player_experience(int experience, killer_type killer, if (exp_gain > 0 && !was_visible) mpr("You feel a bit more experienced."); - if (kc == KC_YOU && you_worship(GOD_BEOGH)) + if (kc == KC_YOU && have_passive(passive_t::share_exp)) _beogh_spread_experience(experience / 2); } @@ -708,7 +709,7 @@ static bool _beogh_forcibly_convert_orc(monster &mons, killer_type killer) static bool _beogh_maybe_convert_orc(monster &mons, killer_type killer, int killer_index) { - if (!in_good_standing(GOD_BEOGH, 2) + if (!have_passive(passive_t::convert_orcs) || mons_genus(mons.type) != MONS_ORC || mons.is_summoned() || mons.is_shapeshifter() || !mons_near(&mons) || mons_is_god_gift(&mons)) @@ -1574,7 +1575,7 @@ static bool _reaping(monster *mons) static bool _god_will_bless_follower(monster* victim) { - return in_good_standing(GOD_BEOGH) + return have_passive(passive_t::bless_followers) && random2(you.piety) >= piety_breakpoint(2) || in_good_standing(GOD_SHINING_ONE) && (victim->is_evil() || victim->is_unholy()) diff --git a/crawl-ref/source/mon-place.cc b/crawl-ref/source/mon-place.cc index 2caccca5b46..0754d92c00d 100644 --- a/crawl-ref/source/mon-place.cc +++ b/crawl-ref/source/mon-place.cc @@ -24,7 +24,7 @@ #include "fprop.h" #include "ghost.h" #include "godabil.h" -#include "godabil.h" +#include "godpassive.h" // passive_t::slow_abyss, slow_orb_run #include "lev-pand.h" #include "libutil.h" #include "losglobal.h" @@ -360,7 +360,7 @@ void spawn_random_monsters() rate = _vestibule_spawn_rate(); if (player_on_orb_run()) - rate = you_worship(GOD_CHEIBRIADOS) ? 16 : 8; + rate = have_passive(passive_t::slow_orb_run) ? 16 : 8; else if (!player_in_starting_abyss()) rate = _scale_spawn_parameter(rate, 6 * rate, 0); @@ -375,7 +375,7 @@ void spawn_random_monsters() { if (!player_in_starting_abyss()) rate = 5; - if (you_worship(GOD_CHEIBRIADOS)) + if (have_passive(passive_t::slow_abyss)) rate *= 2; } diff --git a/crawl-ref/source/mon-transit.cc b/crawl-ref/source/mon-transit.cc index 73bf8272d53..2a100713bae 100644 --- a/crawl-ref/source/mon-transit.cc +++ b/crawl-ref/source/mon-transit.cc @@ -14,6 +14,7 @@ #include "dactions.h" #include "dungeon.h" #include "godcompanions.h" +#include "godpassive.h" // passive_t::convert_orcs #include "items.h" #include "libutil.h" // map_find #include "mon-place.h" @@ -353,7 +354,7 @@ void follower::restore_mons_items(monster& m) static bool _is_religious_follower(const monster* mon) { return (you_worship(GOD_YREDELEMNUL) - || you_worship(GOD_BEOGH) + || will_have_passive(passive_t::convert_orcs) || you_worship(GOD_FEDHAS)) && is_follower(mon); } diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index 3f49668be39..c57fad072ec 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -468,7 +468,7 @@ string describe_mutations(bool center_title) } } - if (beogh_water_walk()) + if (have_passive(passive_t::water_walk)) result += "You can walk on water.\n"; if (you.duration[DUR_FIRE_SHIELD]) @@ -2406,7 +2406,8 @@ void check_monster_detect() if (remembered_monster != mon->type) { const monster_type mc = mon->friendly() ? MONS_SENSED_FRIENDLY - : in_good_standing(GOD_ASHENZARI) ? ash_monster_tier(mon) + : have_passive(passive_t::detect_montier) + ? ash_monster_tier(mon) : MONS_SENSED; env.map_knowledge(*ri).set_detected_monster(mc); diff --git a/crawl-ref/source/orb.cc b/crawl-ref/source/orb.cc index a8ef66cd4b4..4858adc0fcb 100644 --- a/crawl-ref/source/orb.cc +++ b/crawl-ref/source/orb.cc @@ -8,6 +8,7 @@ #include "orb.h" #include "areas.h" +#include "godpassive.h" // passive_t::slow_orb_run #include "shout.h" #include "view.h" #include "religion.h" @@ -79,8 +80,8 @@ void start_orb_run(game_chapter chapter, const char* message) if (you.chapter != CHAPTER_ANGERED_PANDEMONIUM) { mprf(MSGCH_WARN, "The lords of Pandemonium are not amused. Beware!"); - if (you_worship(GOD_CHEIBRIADOS)) - simple_god_message(" tells them not to hurry."); + if (have_passive(passive_t::slow_orb_run)) + simple_god_message(" tells them not to hurry."); } mprf(MSGCH_ORB, "%s", message); diff --git a/crawl-ref/source/ouch.cc b/crawl-ref/source/ouch.cc index 6528557b455..60f630ea727 100644 --- a/crawl-ref/source/ouch.cc +++ b/crawl-ref/source/ouch.cc @@ -688,13 +688,16 @@ static void _powered_by_pain(int dam) static void _maybe_fog(int dam) { + const int minpiety = have_passive(passive_t::hit_smoke) + ? piety_breakpoint(rank_for_passive(passive_t::hit_smoke) - 1) + : piety_breakpoint(2); // Xom + const int upper_threshold = you.hp_max / 2; const int lower_threshold = upper_threshold - upper_threshold - * (you.piety - piety_breakpoint(2)) - / (MAX_PIETY - piety_breakpoint(2)); - if (you_worship(GOD_DITHMENOS) - && you.piety >= piety_breakpoint(2) + * (you.piety - minpiety) + / (MAX_PIETY - minpiety); + if (have_passive(passive_t::hit_smoke) && (dam > 0 && you.form == TRAN_SHADOW || dam >= lower_threshold && x_chance_in_y(dam - lower_threshold, diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index 5685a9aa93c..fb604f4e03c 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -2648,7 +2648,7 @@ static string _status_mut_abilities(int sw) !form_keeps_mutations())); } - if (beogh_water_walk()) + if (have_passive(passive_t::water_walk)) mutations.emplace_back("walk on water"); string current; diff --git a/crawl-ref/source/player-act.cc b/crawl-ref/source/player-act.cc index 43f84603822..1639b8599be 100644 --- a/crawl-ref/source/player-act.cc +++ b/crawl-ref/source/player-act.cc @@ -21,6 +21,7 @@ #include "godabil.h" // RU_SAC_XP_LEVELS #include "godconduct.h" #include "goditem.h" +#include "godpassive.h" // passive_t::no_haste #include "hints.h" #include "itemname.h" #include "itemprop.h" @@ -691,9 +692,11 @@ void player::attacking(actor *other, bool ranged) * messages can be printed if we can't berserk. * @return True if Chei will slow the player, false otherwise. */ -static bool _chei_prevents_berserk_haste(bool intentional) +static bool _god_prevents_berserk_haste(bool intentional) { - if (!you_worship(GOD_CHEIBRIADOS)) + const god_type old_religion = you.religion; + + if (!have_passive(passive_t::no_haste)) return false; // Chei makes berserk not speed you up. @@ -709,7 +712,7 @@ static bool _chei_prevents_berserk_haste(bool intentional) did_god_conduct(DID_HASTY, 8); // Let's see if you've lost your religion... - if (!you_worship(GOD_CHEIBRIADOS)) + if (!you_worship(old_religion)) return false; simple_god_message(" forces you to slow down."); @@ -746,7 +749,7 @@ bool player::go_berserk(bool intentional, bool potion) mpr("Your finesse ends abruptly."); } - if (!_chei_prevents_berserk_haste(intentional)) + if (!_god_prevents_berserk_haste(intentional)) mpr("You feel yourself moving faster!"); mpr("You feel mighty!"); diff --git a/crawl-ref/source/player-reacts.cc b/crawl-ref/source/player-reacts.cc index fb3a92a49e5..880e8a0ee06 100644 --- a/crawl-ref/source/player-reacts.cc +++ b/crawl-ref/source/player-reacts.cc @@ -403,7 +403,7 @@ void player_reacts_to_monsters() check_monster_detect(); - if (in_good_standing(GOD_ASHENZARI) || you.mutation[MUT_JELLY_GROWTH]) + if (have_passive(passive_t::detect_items) || you.mutation[MUT_JELLY_GROWTH]) detect_items(-1); if (you.duration[DUR_TELEPATHY]) @@ -968,7 +968,7 @@ static void _decrement_durations() { int resilience = 400; - if (you_worship(GOD_CHEIBRIADOS) && you.piety >= piety_breakpoint(0)) + if (have_passive(passive_t::slow_metabolism)) resilience = resilience * 3 / 2; // Faster rotting when hungry. diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index ebbd5814c4a..959b674429a 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -398,7 +398,7 @@ static void _splash() { if (you.can_swim()) noisy(4, you.pos(), "Floosh!"); - else if (!beogh_water_walk()) + else if (!have_passive(passive_t::water_walk)) noisy(8, you.pos(), "Splash!"); } @@ -459,7 +459,8 @@ void moveto_location_effects(dungeon_feature_type old_feat, if (feat_is_water(new_grid) && !stepped) _splash(); - if (feat_is_water(new_grid) && !you.can_swim() && !beogh_water_walk()) + if (feat_is_water(new_grid) && !you.can_swim() + && !have_passive(passive_t::water_walk)) { if (stepped) { @@ -586,7 +587,7 @@ bool player_in_connected_branch() bool player_likes_water(bool permanently) { - return !permanently && beogh_water_walk() + return !permanently && have_passive(passive_t::water_walk) || (species_likes_water(you.species) || !permanently) && form_likes_water(); } @@ -1266,7 +1267,7 @@ int player_hunger_rate(bool temp) } // If Cheibriados has slowed your life processes, you will hunger less. - if (you_worship(GOD_CHEIBRIADOS) && you.piety >= piety_breakpoint(0)) + if (have_passive(passive_t::slow_metabolism)) hunger /= 2; if (hunger < 1) @@ -1988,7 +1989,7 @@ int player_movement_speed() mv += you.wearing_ego(EQ_ALL_ARMOUR, SPARM_PONDEROUSNESS); // Cheibriados - if (you_worship(GOD_CHEIBRIADOS)) + if (have_passive(passive_t::slowed)) mv += 2 + min(div_rand_round(you.piety, 20), 8); else if (player_under_penance(GOD_CHEIBRIADOS)) mv += 2 + min(div_rand_round(you.piety_max[GOD_CHEIBRIADOS], 20), 8); @@ -2049,7 +2050,7 @@ int player_speed() if (you.duration[DUR_SLOW] || have_stat_zero()) ps = haste_mul(ps); - if (you.duration[DUR_BERSERK] && !you_worship(GOD_CHEIBRIADOS)) + if (you.duration[DUR_BERSERK] && !have_passive(passive_t::no_haste)) ps = berserk_div(ps); else if (you.duration[DUR_HASTE]) ps = haste_div(ps); @@ -2091,7 +2092,7 @@ static int _player_armour_beogh_bonus(const item_def& item) int bonus = 0; - if (in_good_standing(GOD_BEOGH)) + if (have_passive(passive_t::bonus_ac)) { if (you.piety >= piety_breakpoint(5)) bonus = 10; @@ -3226,7 +3227,7 @@ int check_stealth() if (you.umbra()) { int umbra_mul = 1, umbra_div = 1; - if (you_worship(GOD_DITHMENOS) || you_worship(GOD_YREDELEMNUL)) + if (have_passive(passive_t::umbra) || you_worship(GOD_YREDELEMNUL)) { umbra_mul = you.piety + MAX_PIETY; umbra_div = MAX_PIETY; @@ -3582,7 +3583,7 @@ bool player::clarity(bool calc_unid, bool items) const if (player_mutation_level(MUT_CLARITY)) return true; - if (in_good_standing(GOD_ASHENZARI, 3)) + if (have_passive(passive_t::clarity)) return true; return actor::clarity(calc_unid, items); @@ -4523,7 +4524,7 @@ int poison_survival() if (!get_player_poisoning()) return you.hp; const int rr = player_regen(); - const bool chei = (you.religion == GOD_CHEIBRIADOS && you.piety >= piety_breakpoint(0)); + const bool chei = have_passive(passive_t::slow_metabolism); const bool dd = (you.species == SP_DEEP_DWARF); const int amount = you.duration[DUR_POISONING]; const double full_aut = _poison_dur_to_aut(amount); @@ -5453,7 +5454,7 @@ bool player::is_sufficiently_rested() const bool player::in_water() const { - return ground_level() && !beogh_water_walk() + return ground_level() && !have_passive(passive_t::water_walk) && feat_is_water(grd(pos())); } @@ -5829,7 +5830,7 @@ int player::skill(skill_type sk, int scale, bool real, bool drained) const if (penance[GOD_ASHENZARI]) level = max(level - 4 * scale, level / 2); - else if (in_good_standing(GOD_ASHENZARI, 1)) + else if (have_passive(passive_t::bondage_skill_boost)) { if (skill_boost.count(sk) && skill_boost.find(sk)->second) @@ -6576,8 +6577,7 @@ undead_state_type player::undead_state(bool temp) const bool player::nightvision() const { - return religion == GOD_DITHMENOS && piety >= piety_breakpoint(0) - || religion == GOD_YREDELEMNUL && piety >= piety_breakpoint(2); + return have_passive(passive_t::nightvision); } reach_type player::reach_range() const @@ -7091,7 +7091,7 @@ bool player::can_see_invisible(bool calc_unid, bool items) const if (player_mutation_level(MUT_EYEBALLS) == 3) return true; - if (in_good_standing(GOD_ASHENZARI, 2)) + if (have_passive(passive_t::sinv)) return true; return false; @@ -7757,7 +7757,7 @@ int player_monster_detect_radius() if (player_equip_unrand(UNRAND_BOOTS_ASSASSIN)) radius = max(radius, 4); - if (in_good_standing(GOD_ASHENZARI)) + if (have_passive(passive_t::detect_montier)) radius = max(radius, you.piety / 20); return min(radius, LOS_RADIUS); } diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 6d123d2d7a9..58de7bc991f 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -1148,13 +1148,15 @@ static void _inc_penance(god_type god, int val) you.penance[god] = min((uint8_t)MAX_PENANCE, you.penance[god]); // Orcish bonuses don't apply under penance. - if (god == GOD_BEOGH) - { + if (will_have_passive(passive_t::bonus_ac)) you.redraw_armour_class = true; - if (_need_water_walking() && !beogh_water_walk()) - fall_into_a_pool(grd(you.pos())); + if (will_have_passive(passive_t::water_walk) + && _need_water_walking() && !have_passive(passive_t::water_walk)) + { + fall_into_a_pool(grd(you.pos())); } + // Neither does Trog's regeneration or magic resistance. else if (god == GOD_TROG) { @@ -1518,7 +1520,7 @@ bool is_follower(const monster* mon) { if (you_worship(GOD_YREDELEMNUL)) return is_yred_undead_slave(mon); - else if (you_worship(GOD_BEOGH)) + else if (will_have_passive(passive_t::convert_orcs)) return is_orcish_follower(mon); else if (you_worship(GOD_JIYVA)) return is_fellow_slime(mon); @@ -2255,19 +2257,18 @@ static void _gain_piety_point() } if (you_worship(GOD_SHINING_ONE) && rank == 1) mprf(MSGCH_GOD, "A divine halo surrounds you!"); - if (you_worship(GOD_DITHMENOS) && rank == 1) + if (rank == rank_for_passive(passive_t::umbra)) mprf(MSGCH_GOD, "You are shrouded in an aura of darkness!"); - if (you_worship(GOD_ASHENZARI)) + if (rank == rank_for_passive(passive_t::clarity)) { - if (rank == 3) - { - autotoggle_autopickup(false); - // Inconsistent with donning amulets, but matches the - // message better and is not abusable. - you.duration[DUR_CONF] = 0; - } - auto_id_inventory(); + autotoggle_autopickup(false); + // Inconsistent with donning amulets, but matches the + // message better and is not abusable. + you.duration[DUR_CONF] = 0; } + if (rank >= rank_for_passive(passive_t::identify_items)) + auto_id_inventory(); + if (you_worship(GOD_JIYVA) && can_do_capstone_ability(you.religion)) { simple_god_message(" will now unseal the treasures of the " @@ -2283,18 +2284,22 @@ static void _gain_piety_point() } } - if (you_worship(GOD_BEOGH)) - { - // Every piety level change also affects AC from orcish gear. + // Every piety level change also affects AC. + if (will_have_passive(passive_t::bonus_ac)) you.redraw_armour_class = true; - // The player's symbol depends on Beogh piety. + + // The player's symbol depends on Beogh piety. + if (you_worship(GOD_BEOGH)) update_player_symbol(); - } - if (you_worship(GOD_CHEIBRIADOS) + if (have_passive(passive_t::stat_boost) && chei_stat_boost(old_piety) < chei_stat_boost()) { - simple_god_message(" raises the support of your attributes as your movement slows."); + string msg = " raises the support of your attributes"; + if (have_passive(passive_t::slowed)) + msg += " as your movement slows"; + msg += "."; + simple_god_message(msg.c_str()); notify_stat_change(); } @@ -2304,7 +2309,7 @@ static void _gain_piety_point() you.redraw_armour_class = true; } - if (you_worship(GOD_SHINING_ONE) || you_worship(GOD_DITHMENOS)) + if (you_worship(GOD_SHINING_ONE) || have_passive(passive_t::umbra)) { // Piety change affects halo / umbra radius. invalidate_agrid(true); @@ -2426,18 +2431,23 @@ void lose_piety(int pgn) if (you.piety > 0 && you.piety <= 5) learned_something_new(HINT_GOD_DISPLEASED); - if (you_worship(GOD_BEOGH)) - { - if (_need_water_walking() && !beogh_water_walk()) - fall_into_a_pool(grd(you.pos())); - // Every piety level change also affects AC from orcish gear. + // Every piety level change also affects AC. + if (will_have_passive(passive_t::bonus_ac)) you.redraw_armour_class = true; - } - if (you_worship(GOD_CHEIBRIADOS) + if (will_have_passive(passive_t::water_walk) && _need_water_walking() + && !have_passive(passive_t::water_walk)) + { + fall_into_a_pool(grd(you.pos())); + } + if (will_have_passive(passive_t::stat_boost) && chei_stat_boost(old_piety) > chei_stat_boost()) { - simple_god_message(" reduces the support of your attributes as your movement quickens."); + string msg = " reduces the support of your attributes"; + if (will_have_passive(passive_t::slowed)) + msg += " as your movement quickens"; + msg += "."; + simple_god_message(msg.c_str()); notify_stat_change(); } @@ -2447,7 +2457,7 @@ void lose_piety(int pgn) you.redraw_armour_class = true; } - if (you_worship(GOD_SHINING_ONE) || you_worship(GOD_DITHMENOS)) + if (you_worship(GOD_SHINING_ONE) || have_passive(passive_t::umbra)) { // Piety change affects halo / umbra radius. invalidate_agrid(true); @@ -3101,22 +3111,27 @@ static void _god_welcome_handle_gear() if (you_worship(GOD_ASHENZARI)) { - // Seemingly redundant with auto_id_inventory(), but we don't want to - // announce items where the only new information is their cursedness. - for (auto &item : you.inv) - if (item.defined()) - item.flags |= ISFLAG_KNOW_CURSE; - if (!item_type_known(OBJ_SCROLLS, SCR_REMOVE_CURSE)) { set_ident_type(OBJ_SCROLLS, SCR_REMOVE_CURSE, true); pack_item_identify_message(OBJ_SCROLLS, SCR_REMOVE_CURSE); } + } + + if (have_passive(passive_t::identify_items)) + { + // Seemingly redundant with auto_id_inventory(), but we don't want to + // announce items where the only new information is their cursedness. + for (auto &item : you.inv) + if (item.defined()) + item.flags |= ISFLAG_KNOW_CURSE; auto_id_inventory(); - ash_detect_portals(true); } + if (have_passive(passive_t::detect_portals)) + ash_detect_portals(true); + // Give a reminder to remove any disallowed equipment. for (int i = EQ_MIN_ARMOUR; i < EQ_MAX_ARMOUR; i++) { @@ -3278,20 +3293,21 @@ void join_religion(god_type which_god, bool immediate) gain_piety(30, 1, false); } + // The player's symbol depends on Beogh worship. if (you_worship(GOD_BEOGH)) - { - // The player's symbol depends on Beogh worship. update_player_symbol(); - } _god_welcome_handle_gear(); ash_check_bondage(); // Chei worshippers start their stat gain immediately. - if (you_worship(GOD_CHEIBRIADOS)) + if (have_passive(passive_t::stat_boost)) { - simple_god_message(" begins to support your attributes as your " - "movement slows."); + string msg = " begins to support your attributes"; + if (have_passive(passive_t::slowed)) + msg += " as your movement slows"; + msg += "."; + simple_god_message(msg.c_str()); notify_stat_change(); } @@ -4398,8 +4414,11 @@ static void _place_delayed_monsters() if (mon) { - if (you_worship(GOD_YREDELEMNUL) || you_worship(GOD_BEOGH)) + if (you_worship(GOD_YREDELEMNUL) + || have_passive(passive_t::convert_orcs)) + { add_companion(mon); + } placed++; } diff --git a/crawl-ref/source/skill_menu.cc b/crawl-ref/source/skill_menu.cc index 2fc37a368da..6ed82c28a7e 100644 --- a/crawl-ref/source/skill_menu.cc +++ b/crawl-ref/source/skill_menu.cc @@ -12,7 +12,9 @@ #include "clua.h" #include "command.h" #include "describe.h" +#include "english.h" // apostrophise #include "evoke.h" +#include "godpassive.h" // passive_t::bondage_skill_boost #include "hints.h" #include "options.h" #include "output.h" @@ -567,11 +569,15 @@ string SkillMenuSwitch::get_help() string result; if (skm.is_set(SKMF_ENHANCED)) { - vector causes; + vector causes; if (you.duration[DUR_HEROISM]) causes.push_back("Heroism"); - if (!you.skill_boost.empty() && in_good_standing(GOD_ASHENZARI, 3)) - causes.push_back("Ashenzari's power"); + if (!you.skill_boost.empty() + && have_passive(passive_t::bondage_skill_boost)) + { + causes.push_back(apostrophise(god_name(you.religion)) + + " power"); + } if (_any_crosstrained()) causes.push_back("cross-training"); if (player_equip_unrand(UNRAND_FENCERS)) diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc index 3239c03d2be..567aba054ec 100644 --- a/crawl-ref/source/spl-cast.cc +++ b/crawl-ref/source/spl-cast.cc @@ -27,6 +27,7 @@ #include "godabil.h" #include "godconduct.h" #include "goditem.h" +#include "godpassive.h" // passive_t::shadow_spells #include "hints.h" #include "item_use.h" #include "libutil.h" @@ -1468,9 +1469,9 @@ spret_type your_spells(spell_type spell, int powc, if (you.props.exists("battlesphere") && allow_fail) trigger_battlesphere(&you, beam); actor* victim = actor_at(beam.target); - if (you_worship(GOD_DITHMENOS) + if (will_have_passive(passive_t::shadow_spells) && allow_fail - && !god_hates_spell(spell, GOD_DITHMENOS, !allow_fail) + && !god_hates_spell(spell, you.religion, !allow_fail) && (flags & SPFLAG_TARGETING_MASK) && !(flags & SPFLAG_NEUTRAL) && (beam.is_enchantment() diff --git a/crawl-ref/source/spl-goditem.cc b/crawl-ref/source/spl-goditem.cc index 6b4546624ef..e57b0f449d5 100644 --- a/crawl-ref/source/spl-goditem.cc +++ b/crawl-ref/source/spl-goditem.cc @@ -507,7 +507,7 @@ int detect_items(int pow) map_radius = 7 + random2(7) + pow; else { - if (you_worship(GOD_ASHENZARI)) + if (have_passive(passive_t::detect_items)) { map_radius = min(you.piety / 20 - 1, LOS_RADIUS); if (map_radius <= 0) @@ -667,7 +667,7 @@ static bool _selectively_remove_curse(const string &pre_msg) bool remove_curse(bool alreadyknown, const string &pre_msg) { - if (you_worship(GOD_ASHENZARI) && alreadyknown) + if (have_passive(passive_t::want_curses) && alreadyknown) { if (_selectively_remove_curse(pre_msg)) { diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc index b3c1ec19735..91b81f817a0 100644 --- a/crawl-ref/source/stairs.cc +++ b/crawl-ref/source/stairs.cc @@ -19,6 +19,7 @@ #include "files.h" #include "fprop.h" #include "godabil.h" +#include "godpassive.h" // passive_t::slow_abyss #include "hints.h" #include "hiscores.h" #include "itemname.h" @@ -676,10 +677,11 @@ void floor_transition(dungeon_feature_type how, mpr("You enter the Abyss!"); mpr("To return, you must find a gate leading back."); - if (you_worship(GOD_CHEIBRIADOS)) + if (have_passive(passive_t::slow_abyss)) { - mprf(MSGCH_GOD, GOD_CHEIBRIADOS, - "You feel Cheibriados slowing down the madness of this place."); + mprf(MSGCH_GOD, you.religion, + "You feel %s slowing down the madness of this place.", + god_name(you.religion).c_str()); } // Re-entering the Abyss halves accumulated speed. diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc index bdc0fcd375a..740ebf39259 100644 --- a/crawl-ref/source/stash.cc +++ b/crawl-ref/source/stash.cc @@ -2244,7 +2244,7 @@ void StashTracker::update_corpses() void StashTracker::update_identification() { - if (!you_worship(GOD_ASHENZARI)) + if (!have_passive(passive_t::identify_items)) return; for (auto &entry : levels) diff --git a/crawl-ref/source/terrain.cc b/crawl-ref/source/terrain.cc index 77ce8d381fb..fde26d29729 100644 --- a/crawl-ref/source/terrain.cc +++ b/crawl-ref/source/terrain.cc @@ -24,6 +24,7 @@ #include "feature.h" #include "fprop.h" #include "godabil.h" +#include "godpassive.h" // passive_t::water_walk #include "itemprop.h" #include "items.h" #include "libutil.h" @@ -1480,7 +1481,7 @@ void fall_into_a_pool(dungeon_feature_type terrain) { if (terrain == DNGN_DEEP_WATER) { - if (beogh_water_walk() || form_likes_water()) + if (have_passive(passive_t::water_walk) || form_likes_water()) return; if (species_likes_water(you.species) && !you.transform_uncancellable) diff --git a/crawl-ref/source/throw.cc b/crawl-ref/source/throw.cc index be843d1e359..a5f36bda6e5 100644 --- a/crawl-ref/source/throw.cc +++ b/crawl-ref/source/throw.cc @@ -18,6 +18,7 @@ #include "exercise.h" #include "godabil.h" #include "godconduct.h" +#include "godpassive.h" // passive_t::shadow_attacks #include "hints.h" #include "invent.h" #include "itemprop.h" @@ -960,7 +961,7 @@ bool throw_it(bolt &pbolt, int throw_2, dist *target) if (!teleport && projected - && you_worship(GOD_DITHMENOS) + && will_have_passive(passive_t::shadow_attacks) && thrown.base_type == OBJ_MISSILES && thrown.sub_type != MI_NEEDLE) { diff --git a/crawl-ref/source/timed_effects.cc b/crawl-ref/source/timed_effects.cc index d95b7da64bd..ae42e8f2e33 100644 --- a/crawl-ref/source/timed_effects.cc +++ b/crawl-ref/source/timed_effects.cc @@ -819,9 +819,7 @@ static void _handle_sickness(int /*time_delta*/) // If Cheibriados has slowed your biology, disease might // not actually do anything. if (you.disease && one_chance_in(30) - && !(you_worship(GOD_CHEIBRIADOS) - && you.piety >= piety_breakpoint(0) - && coinflip())) + && !(have_passive(passive_t::slow_metabolism) && coinflip())) { mprf(MSGCH_WARN, "Your disease is taking its toll."); lose_stat(STAT_RANDOM, 1); @@ -847,7 +845,7 @@ static void _abyss_speed(int /*time_delta*/) if (!player_in_branch(BRANCH_ABYSS)) return; - if (you_worship(GOD_CHEIBRIADOS) && coinflip()) + if (have_passive(passive_t::slow_abyss) && coinflip()) ; // Speed change less often for Chei. else if (coinflip() && you.abyss_speed < 100) ++you.abyss_speed; diff --git a/crawl-ref/source/transform.cc b/crawl-ref/source/transform.cc index 02ef7923c77..86b25430caa 100644 --- a/crawl-ref/source/transform.cc +++ b/crawl-ref/source/transform.cc @@ -18,6 +18,7 @@ #include "env.h" #include "godabil.h" #include "goditem.h" +#include "godpassive.h" // passive_t::water_walk #include "item_use.h" #include "itemname.h" #include "itemprop.h" @@ -1460,10 +1461,8 @@ bool feat_dangerous_for_form(transformation_type which_trans, if (feat == DNGN_DEEP_WATER) { - if (beogh_water_walk()) - return false; - - return !form_likes_water(which_trans); + return !have_passive(passive_t::water_walk) + && !form_likes_water(which_trans); } return false; diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index 6179fe73316..34d93c1527f 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -23,6 +23,7 @@ #include "dungeon.h" #include "english.h" #include "exercise.h" +#include "godpassive.h" // passive_t::search_traps #include "hints.h" #include "itemprop.h" #include "items.h" @@ -1082,7 +1083,7 @@ void search_around() int skill = (2/(1+exp(-(base_skill+120)/325.0))-1) * 225 + (base_skill/200.0) + 15; - if (in_good_standing(GOD_ASHENZARI)) + if (have_passive(passive_t::search_traps)) skill += you.piety * 2; int max_dist = div_rand_round(skill, 32); diff --git a/crawl-ref/source/wiz-item.cc b/crawl-ref/source/wiz-item.cc index f671f56c326..d001992c108 100644 --- a/crawl-ref/source/wiz-item.cc +++ b/crawl-ref/source/wiz-item.cc @@ -614,7 +614,7 @@ void wizard_make_object_randart() } // Remove curse flag from item, unless worshipping Ashenzari. - if (you_worship(GOD_ASHENZARI)) + if (have_passive(passive_t::want_curses)) do_curse_item(item, true); else do_uncurse_item(item, false);