diff options
-rw-r--r-- | crawl-ref/source/beam.cc | 11 | ||||
-rw-r--r-- | crawl-ref/source/enum.h | 5 | ||||
-rw-r--r-- | crawl-ref/source/mon-data.h | 2 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 23 | ||||
-rw-r--r-- | crawl-ref/source/religion.cc | 11 | ||||
-rw-r--r-- | crawl-ref/source/spells1.cc | 127 | ||||
-rw-r--r-- | crawl-ref/source/spells1.h | 2 |
7 files changed, 148 insertions, 33 deletions
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index 7e637a96cf..7c44cdf1df 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -2080,7 +2080,16 @@ int mons_ench_f2(monsters *monster, bolt &pbolt) return (MON_AFFECTED); case BEAM_HEALING: /* 2 = healing */ - if (heal_monster( monster, 5 + roll_dice( pbolt.damage ), false )) + if (YOU_KILL(pbolt.thrower)) + { + if (cast_healing(5 + roll_dice( pbolt.damage ), + monster->x - you.x_pos, monster->y - you.y_pos) > 0) + { + pbolt.obvious_effect = true; + } + pbolt.msg_generated = true; // to avoid duplicate "nothing happens" + } + else if (heal_monster( monster, 5 + roll_dice( pbolt.damage ), false )) { if (monster->hit_points == monster->max_hit_points) { diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index 59cfb51ef9..49fcf96304 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -641,7 +641,7 @@ enum conduct_type DID_KILL_WIZARD, DID_KILL_PRIEST, DID_KILL_HOLY, - DID_KILL_NEUTRAL, // unused + DID_KILL_NEUTRAL, DID_LIVING_KILLED_BY_UNDEAD_SLAVE, DID_LIVING_KILLED_BY_SERVANT, DID_UNDEAD_KILLED_BY_SERVANT, @@ -1887,7 +1887,8 @@ enum monster_flag_type // (good god worshippers -> neutral) // and orcs (Beogh worshippers -> friendly) MF_WAS_IN_VIEW = 0x2000, // Was in view during previous turn - MF_BAND_MEMBER = 0x4000 // Created as a member of a band + MF_BAND_MEMBER = 0x4000, // Created as a member of a band + MF_GOT_HALF_XP = 0x8000 // player already got half xp value earlier }; // Adding slots breaks saves. YHBW. diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h index 1058e4b926..e9d640b065 100644 --- a/crawl-ref/source/mon-data.h +++ b/crawl-ref/source/mon-data.h @@ -97,7 +97,7 @@ - various things monsters can do upon seeing you intel explanation: - - How smart it is: I_PLANT < I_ANIMAL < I_NORMAL < I_HIGH. + - How smart it is: I_PLANT < I_INSECT < I_ANIMAL < I_NORMAL < I_HIGH. So far, differences here have little effects except for monster's chance of seeing you if stealthy and rudimentary trap handling; really stupid monsters will walk through clouds diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index b293160a48..e08685c1cb 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -392,7 +392,7 @@ static void check_kill_milestone(const monsters *mons, } #endif // DGL_MILESTONES -static void give_monster_experience( monsters *victim, +static void _give_monster_experience( monsters *victim, int killer_index, int experience, bool victim_was_born_friendly ) { @@ -421,27 +421,34 @@ static void give_adjusted_experience(monsters *monster, killer_type killer, testbits(monster->flags, MF_CREATED_FRIENDLY); const bool was_neutral = testbits(monster->flags, MF_WAS_NEUTRAL); const bool no_xp = monster->has_ench(ENCH_ABJ); + const bool already_got_half_xp = testbits(monster->flags, MF_GOT_HALF_XP); if (created_friendly || was_neutral || no_xp) ; // No experience if monster was created friendly or summoned. else if (YOU_KILL(killer)) { int old_lev = you.experience_level; - gain_exp( experience, exp_gain, avail_gain ); + if (already_got_half_xp) + gain_exp( experience / 2, exp_gain, avail_gain ); + else + gain_exp( experience, exp_gain, avail_gain ); + // Give a message for monsters dying out of sight if (exp_gain > 0 && !mons_near(monster) && you.experience_level == old_lev) + { mpr("You feel a bit more experienced."); + } } - else if (pet_kill) + else if (pet_kill && !already_got_half_xp) gain_exp( experience / 2 + 1, exp_gain, avail_gain ); if (MON_KILL(killer) && !no_xp) - give_monster_experience( monster, killer_index, experience, - created_friendly ); + _give_monster_experience( monster, killer_index, experience, + created_friendly ); } -static bool is_pet_kill(killer_type killer, int i) +static bool _is_pet_kill(killer_type killer, int i) { if (!MON_KILL(killer)) return (false); @@ -670,7 +677,7 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent) if (killer == KILL_YOU) crawl_state.cancel_cmd_repeat(); - const bool pet_kill = is_pet_kill(killer, i); + const bool pet_kill = _is_pet_kill(killer, i); if (monster->type == MONS_GIANT_SPORE || monster->type == MONS_BALL_LIGHTNING) @@ -789,7 +796,7 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent) did_god_conduct(DID_KILL_HOLY, monster->hit_dice, true, monster); - if (created_friendly) + if (was_neutral) did_god_conduct(DID_KILL_NEUTRAL, monster->hit_dice, true, monster); } diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index da043726bc..01f537ef13 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -1446,6 +1446,16 @@ bool did_god_conduct( conduct_type thing_done, int level, bool known, } break; + case DID_KILL_NEUTRAL: + if (you.religion == GOD_ELYVILON) + { + simple_god_message(" did not appreciate that!"); + ret = true; + piety_change = -(level/2 + 1); + penance = std::min(level, 5); + } + break; + case DID_KILL_LIVING: switch (you.religion) { @@ -1812,7 +1822,6 @@ bool did_god_conduct( conduct_type thing_done, int level, bool known, } break; - case DID_KILL_NEUTRAL: // unused case DID_STIMULANTS: // unused case DID_EAT_MEAT: // unused case DID_CREATED_LIFE: // unused diff --git a/crawl-ref/source/spells1.cc b/crawl-ref/source/spells1.cc index 8b65313412..354be9f688 100644 --- a/crawl-ref/source/spells1.cc +++ b/crawl-ref/source/spells1.cc @@ -42,6 +42,7 @@ #include "mon-util.h" #include "player.h" #include "randart.h" +#include "religion.h" #include "skills2.h" #include "spells3.h" #include "spells4.h" @@ -571,32 +572,86 @@ int cast_big_c(int pow, cloud_type cty, kill_category whose, bolt &beam) big_cloud( cty, whose, beam.target_x, beam.target_y, pow, 8 + random2(3) ); return (1); -} // end cast_big_c() +} void big_cloud(cloud_type cl_type, kill_category whose, int cl_x, int cl_y, int pow, int size, int spread_rate) { apply_area_cloud(make_a_normal_cloud, cl_x, cl_y, pow, size, cl_type, whose, spread_rate); -} // end big_cloud() +} + +static bool _mons_hostile(const monsters *mon) +{ + // needs to be done this way because of friendly/neutral enchantments + return (!mons_friendly(mon) && !mons_neutral(mon)); +} + +static bool _can_pacify_monster(const monsters *mon, const int healed) +{ + ASSERT(you.religion == GOD_ELYVILON); + + if (healed < 1) + return false; + + if (mons_friendly(mon) || mons_neutral(mon)) + return false; + + // Ely only cares about natural monsters + if (mons_holiness(mon) != MH_NATURAL) + return false; + + if (mons_intel(mon->type) <= I_PLANT) // no self-awareness + return false; + + if (mons_is_sleeping(mon)) // not aware of what is happening + return false; -static int healing_spell( int healed ) + const int factor = (mons_intel(mon->type) <= I_ANIMAL) ? 3 : // animals + (is_player_same_species(mon->type)) ? 2 // same species + : 1; // other + + const int random_factor = random2(you.skills[SK_INVOCATIONS] * healed/3); + +#ifdef DEBUG_DIAGNOSTICS + mprf(MSGCH_DIAGNOSTICS, + "pacifying %s? max hp: %d, factor: %d, Inv: %d, healed: %d, rnd: %d", + mon->name(DESC_PLAIN).c_str(), mon->max_hit_points, factor, + you.skills[SK_INVOCATIONS], healed, random_factor); +#endif + + if (mon->max_hit_points < factor * random_factor) + return true; + + return false; +} + +static int _healing_spell( int healed, int dir_x = 100, int dir_y = 100) { + ASSERT(healed >= 1); + int mgr = 0; struct monsters *monster = 0; // NULL {dlb} struct dist bmove; - mpr("Which direction?", MSGCH_PROMPT); - direction( bmove, DIR_DIR, TARG_FRIEND ); - + if (dir_x == 100 || dir_y == 100) + { + mpr("Which direction?", MSGCH_PROMPT); + direction( bmove, DIR_DIR, TARG_FRIEND ); + } + else + { + bmove.dx = dir_x; + bmove.dy = dir_y; + bmove.isValid = true; + } + if (!bmove.isValid) { canned_msg( MSG_OK ); return 0; } - mgr = mgrd[you.x_pos + bmove.dx][you.y_pos + bmove.dy]; - if (bmove.dx == 0 && bmove.dy == 0) { mpr("You are healed."); @@ -604,6 +659,8 @@ static int healing_spell( int healed ) return 1; } + mgr = mgrd[you.x_pos + bmove.dx][you.y_pos + bmove.dy]; + if (mgr == NON_MONSTER) { mpr("There isn't anything there!"); @@ -611,7 +668,16 @@ static int healing_spell( int healed ) } monster = &menv[mgr]; + + // don't heal monster you can't pacify + if (you.religion == GOD_ELYVILON && _mons_hostile(monster) + && !_can_pacify_monster(monster, healed)) + { + canned_msg(MSG_NOTHING_HAPPENS); + return -1; + } + bool nothing_happens = true; if (heal_monster(monster, healed, false)) { mprf("You heal %s.", monster->name(DESC_NOCAP_THE).c_str()); @@ -623,38 +689,61 @@ static int healing_spell( int healed ) const monsters *mons = static_cast<const monsters*>(monster); print_wounds(mons); } + + if (you.religion == GOD_ELYVILON && !_mons_hostile(monster)) + { + simple_god_message(" appreciates the healing of a fellow creature."); + if (one_chance_in(8)) + gain_piety(1); + return 1; + } + nothing_happens = false; } - else + + if (you.religion == GOD_ELYVILON && _mons_hostile(monster)) { - canned_msg(MSG_NOTHING_HAPPENS); + simple_god_message(" supports your offer of peace."); + simple_monster_message( monster, " turns neutral." ); + monster->attitude = ATT_NEUTRAL; + monster->flags |= MF_WAS_NEUTRAL; + + // give half of the monster's xp + unsigned int exp_gain = 0, avail_gain = 0; + gain_exp( exper_value(monster) / 2 + 1, &exp_gain, &avail_gain ); + monster->flags |= MF_GOT_HALF_XP; + + // finally give a small piety return + gain_piety(1 + random2(healed/15)); } + else if (nothing_happens) + canned_msg(MSG_NOTHING_HAPPENS); return 1; -} // end healing_spell() +} // end _healing_spell() #if 0 char cast_lesser_healing( int pow ) { - return healing_spell(5 + random2avg(7, 2)); -} // end lesser healing() + return _healing_spell(5 + random2avg(7, 2)); +} char cast_greater_healing( int pow ) { - return healing_spell(15 + random2avg(29, 2)); -} // end cast_greater_healing() + return _healing_spell(15 + random2avg(29, 2)); +} char cast_greatest_healing( int pow ) { - return healing_spell(50 + random2avg(49, 2)); -} // end cast_greatest_healing() + return _healing_spell(50 + random2avg(49, 2)); +} #endif -int cast_healing( int pow ) +int cast_healing( int pow, int dir_x, int dir_y ) { if (pow > 50) pow = 50; - return (healing_spell( pow + roll_dice( 2, pow ) - 2 )); + return (_healing_spell( pow + roll_dice( 2, pow ) - 2, dir_x, dir_y )); } int cast_revitalisation( int pow ) diff --git a/crawl-ref/source/spells1.h b/crawl-ref/source/spells1.h index b945a4cc78..f7a7f92fe4 100644 --- a/crawl-ref/source/spells1.h +++ b/crawl-ref/source/spells1.h @@ -53,7 +53,7 @@ char cast_lesser_healing(void); /* *********************************************************************** * called from: ability - spell * *********************************************************************** */ -int cast_healing(int power); +int cast_healing(int power, int dir_x = 100, int dir_y = 100); int cast_revitalisation(int power); // last updated 24may2000 {dlb} |