diff options
-rw-r--r-- | crawl-ref/source/fight.cc | 14 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 59 | ||||
-rw-r--r-- | crawl-ref/source/religion.cc | 99 |
3 files changed, 169 insertions, 3 deletions
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index cf79b80318..90ff0255cb 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -910,7 +910,16 @@ bool melee_attack::player_aux_unarmed() // XXX We're clobbering did_hit did_hit = false; - if (to_hit >= def->ev || one_chance_in(30)) + + bool ely_block = false; + if (you.religion != GOD_ELYVILON && you.penance[GOD_ELYVILON] + && to_hit >= def->ev && one_chance_in(20)) + { + simple_god_message(" blocks your attack.", GOD_ELYVILON); + ely_block = true; + } + + if (!ely_block && (to_hit >= def->ev || one_chance_in(30))) { if (attack_shield_blocked(true)) continue; @@ -927,6 +936,9 @@ bool melee_attack::player_aux_unarmed() miss_verb.empty()? unarmed_attack.c_str() : miss_verb.c_str(), defender->name(DESC_NOCAP_THE).c_str()); + + if (ely_block) + dec_penance(GOD_ELYVILON, 1 + random2(to_hit - def->ev)); } } diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index 2ea6e4d33c..29737e2917 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -462,14 +462,73 @@ static bool is_pet_kill(killer_type killer, int i) && (me.who == KC_YOU || me.who == KC_FRIENDLY)); } +static bool ely_heals_monster(monsters *monster, killer_type killer, int i) +{ + god_type god = GOD_ELYVILON; + ASSERT(you.religion != god); + + const int ely_penance = you.penance[god]; + ASSERT(ely_penance > 0); + + if (mons_holiness(monster) != MH_NATURAL + || mons_friendly(monster) + || !one_chance_in(10)) + { + return (false); + } + + if (MON_KILL(killer)) + { + monsters *mon = &menv[i]; + if (!mons_friendly(mon) || !one_chance_in(3)) + return (false); + + if (!mons_near(monster)) + return (false); + } + else if (!YOU_KILL(killer)) + return (false); + +#ifdef DEBUG_DIAGNOSTICS + mprf(MSGCH_DIAGNOSTICS, "monster hp: %d, max hp: %d", + monster->hit_points, monster->max_hit_points); +#endif + + monster->hit_points = std::min(1 + random2(ely_penance/3), + monster->max_hit_points); + +#ifdef DEBUG_DIAGNOSTICS + mprf(MSGCH_DIAGNOSTICS, "new hp: %d, ely penance: %d", + monster->hit_points, ely_penance); +#endif + + snprintf(info, INFO_SIZE, "%s heals %s%s", + god_name(god, false).c_str(), + monster->name(DESC_NOCAP_THE).c_str(), + monster->hit_points * 2 <= monster->max_hit_points ? "." : "!"); + + god_speaks(god, info); + dec_penance(god, 1 + random2(monster->hit_points/2)); + + return (true); +} + static bool monster_avoided_death(monsters *monster, killer_type killer, int i) { if (monster->hit_points < -25 || monster->hit_points < -monster->max_hit_points || monster->max_hit_points <= 0 || monster->hit_dice < 1) + { return (false); + } + if (you.religion != GOD_ELYVILON && you.penance[GOD_ELYVILON] + && ely_heals_monster(monster, killer, i)) + { + return (true); + } + bool convert = false; if (you.religion == GOD_BEOGH diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index b68a938e2b..72287b1c6e 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -2793,6 +2793,100 @@ static bool nemelex_retribution() return true; } +static void ely_destroy_inventory_weapon() +{ + int count = 0; + int item = ENDOFPACK; + + for (int i = 0; i < ENDOFPACK; i++) + { + if (!is_valid_item( you.inv[i] )) + continue; + + if (you.inv[i].base_type == OBJ_WEAPONS + || you.inv[i].base_type == OBJ_MISSILES) + { + if (is_artefact(you.inv[i])) + continue; + + // item is valid for destroying, so give it a chance + count++; + if (one_chance_in( count )) + item = i; + } + } + + // any item to destroy? + if (item == ENDOFPACK) + return; + + int value = 1; + bool wielded = false; + + // increase value wielded weapons or large stacks of ammo + if (you.inv[item].base_type == OBJ_WEAPONS + && you.inv[item].link == you.equip[EQ_WEAPON]) + { + wielded = true; + value += 2; + } + else if (you.inv[item].quantity > random2(you.penance[GOD_ELYVILON])) + value += 1 + random2(2); + + std::ostream& strm = msg::streams(MSGCH_GOD); + strm << you.inv[item].name(DESC_CAP_YOUR); + + if (value == 1) + strm << " barely"; + + if ( you.inv[item].quantity == 1 ) + strm << " shimmers and breaks into pieces." << std::endl; + else + strm << " shimmer and break into pieces." << std::endl; + + if (wielded) + { + unwield_item(true); + you.wield_change = true; + } + // just in case + you.quiver_change = true; + + destroy_item(you.inv[item]); + burden_change(); + + dec_penance(GOD_ELYVILON, value); +} + +// comparatively lenient +static bool elyvilon_retribution() +{ + const god_type god = GOD_ELYVILON; + + simple_god_message("'s displeasure finds you.", god); + + // healing theme and interfering with fighting + switch (random2(5)) + { + case 0: + case 1: + confuse_player( 3 + random2(10), false ); + break; + + case 2: // mostly flavour messages + miscast_effect(SPTYP_POISON, 0, 0, one_chance_in(3), + "the will of Elyvilon"); + break; + + case 3: + case 4: // destroy weapons in your inventory + ely_destroy_inventory_weapon(); + break; + } + + return true; +} + void divine_retribution( god_type god ) { ASSERT(god != GOD_NO_GOD); @@ -2821,8 +2915,8 @@ void divine_retribution( god_type god ) case GOD_VEHUMET: do_more = vehumet_retribution(); break; case GOD_NEMELEX_XOBEH: do_more = nemelex_retribution(); break; case GOD_SIF_MUNA: do_more = sif_muna_retribution(); break; + case GOD_ELYVILON: do_more = elyvilon_retribution(); break; - case GOD_ELYVILON: // Elyvilon doesn't seek revenge default: do_more = false; break; @@ -3401,7 +3495,8 @@ void excommunication(god_type new_god) inc_penance(old_god, 50); break; - case GOD_ELYVILON: // never seeks revenge + case GOD_ELYVILON: + inc_penance( old_god, 50 ); break; case GOD_SHINING_ONE: |