diff options
-rw-r--r-- | crawl-ref/source/beam.cc | 25 | ||||
-rw-r--r-- | crawl-ref/source/beam.h | 5 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.cc | 7 | ||||
-rw-r--r-- | crawl-ref/source/externs.h | 31 | ||||
-rw-r--r-- | crawl-ref/source/fight.cc | 6 | ||||
-rw-r--r-- | crawl-ref/source/it_use2.cc | 3 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.cc | 31 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/mstuff2.cc | 23 | ||||
-rw-r--r-- | crawl-ref/source/player.cc | 8 | ||||
-rw-r--r-- | crawl-ref/source/religion.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/spl-cast.cc | 53 |
12 files changed, 143 insertions, 53 deletions
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index 248c50f04c..13644d9d7d 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -2562,7 +2562,7 @@ bool curare_hits_monster(actor *agent, monsters *monster, kill_category who, } if (monster->alive()) - enchant_monster_with_flavour(monster, BEAM_SLOW); + enchant_monster_with_flavour(monster, agent, BEAM_SLOW); } // Deities take notice. @@ -3593,7 +3593,7 @@ void bolt::affect_player_enchantment() { break; case BEAM_PETRIFY: - you.petrify( ench_power ); + you.petrify( agent(), ench_power ); obvious_effect = true; break; @@ -4608,11 +4608,13 @@ bool _ench_flavour_affects_monster(beam_type flavour, const monsters* mon) return rc; } -bool enchant_monster_with_flavour(monsters* mon, beam_type flavour, int powc) +bool enchant_monster_with_flavour(monsters* mon, actor *foe, + beam_type flavour, int powc) { bolt dummy; dummy.flavour = flavour; dummy.ench_power = powc; + dummy.set_agent(foe); dummy.apply_enchantment_to_monster(mon); return dummy.obvious_effect; } @@ -5462,6 +5464,23 @@ void bolt::setup_retrace() aimed_at_spot = true; } +void bolt::set_agent(actor *actor) +{ + // NULL actor is fine by us. + if (!actor) + return; + + if (actor->atype() == ACT_PLAYER) + { + thrower = KILL_YOU_MISSILE; + } + else + { + thrower = KILL_MON_MISSILE; + beam_source = monster_index(dynamic_cast<monsters*>(actor)); + } +} + actor* bolt::agent() const { if (YOU_KILL(this->thrower)) diff --git a/crawl-ref/source/beam.h b/crawl-ref/source/beam.h index e88008f4ec..bec6360a0c 100644 --- a/crawl-ref/source/beam.h +++ b/crawl-ref/source/beam.h @@ -118,6 +118,7 @@ public: bool is_enchantment() const; // no block/dodge, use magic resist void set_target(const dist &targ); + void set_agent(actor *agent); void setup_retrace(); // Returns YOU_KILL or MON_KILL, depending on the source of the beam. @@ -245,8 +246,8 @@ int mons_adjust_flavoured(monsters *monster, bolt &pbolt, int hurted, bool doFlavouredEffects = true); // Return whether the effect was visible. -bool enchant_monster_with_flavour(monsters* mon, beam_type flavour, - int powc = 0); +bool enchant_monster_with_flavour(monsters* mon, actor *atk, + beam_type flavour, int powc = 0); // returns true if messages were generated during the enchantment bool mass_enchantment( enchant_type wh_enchant, int pow, int who, diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 4df4bf78df..3342bf40fe 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -925,6 +925,13 @@ static void _reset_level() menv[i].reset(); env.mons_alloc.init(MONS_PROGRAM_BUG); + + // Zap clouds + env.cgrid.init(EMPTY_CLOUD); + + const cloud_struct empty; + env.cloud.init(empty); + mgrd.init(NON_MONSTER); igrd.init(NON_ITEM); diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h index 4c11d2a6e0..134c247218 100644 --- a/crawl-ref/source/externs.h +++ b/crawl-ref/source/externs.h @@ -338,10 +338,10 @@ public: virtual void teleport(bool right_now = false, bool abyss_shift = false) = 0; virtual void poison(actor *attacker, int amount = 1) = 0; virtual bool sicken(int amount) = 0; - virtual void paralyse(int strength) = 0; - virtual void petrify(int strength) = 0; - virtual void slow_down(int strength) = 0; - virtual void confuse(int strength) = 0; + virtual void paralyse(actor *attacker, int strength) = 0; + virtual void petrify(actor *attacker, int strength) = 0; + virtual void slow_down(actor *attacker, int strength) = 0; + virtual void confuse(actor *attacker, int strength) = 0; virtual void rot(actor *attacker, int rotlevel, int immediate_rot) = 0; virtual void expose_to_element(beam_type element, int strength = 0) = 0; virtual void drain_stat(int stat, int amount, actor* attacker) { } @@ -1061,10 +1061,10 @@ public: void make_hungry(int nutrition, bool silent = true); void poison(actor *agent, int amount = 1); bool sicken(int amount); - void paralyse(int str); - void petrify(int str); - void slow_down(int str); - void confuse(int strength); + void paralyse(actor *, int str); + void petrify(actor *, int str); + void slow_down(actor *, int str); + void confuse(actor *, int strength); void rot(actor *agent, int rotlevel, int immed_rot); void heal(int amount, bool max_too = false); int hurt(const actor *attacker, int amount, @@ -1323,6 +1323,8 @@ public: void react_to_damage(int damage, beam_type flavour); + void forget_random_spell(); + void add_enchantment_effect(const mon_enchant &me, bool quiet = false); void remove_enchantment_effect(const mon_enchant &me, bool quiet = false); void apply_enchantments(); @@ -1489,10 +1491,10 @@ public: void poison(actor *agent, int amount = 1); bool sicken(int strength); - void paralyse(int str); - void petrify(int str); - void slow_down(int str); - void confuse(int strength); + void paralyse(actor *, int str); + void petrify(actor *, int str); + void slow_down(actor *, int str); + void confuse(actor *, int strength); void rot(actor *agent, int rotlevel, int immed_rot); int hurt(const actor *attacker, int amount, beam_type flavour = BEAM_MISSILE, @@ -1559,6 +1561,11 @@ struct cloud_struct kill_category whose; killer_type killer; + cloud_struct() : pos(), type(CLOUD_NONE), decay(0), spread_rate(0), + whose(KC_OTHER), killer(KILL_NONE) + { + } + void set_whose(kill_category _whose); void set_killer(killer_type _killer); diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index 5f8ed20af7..1f9c08369e 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -4215,9 +4215,9 @@ void melee_attack::wasp_paralyse_defender() if (defender->res_poison() <= 0) { if (one_chance_in(paralyse_roll)) - defender->paralyse( roll_dice(1, 3) ); + defender->paralyse( attacker, roll_dice(1, 3) ); else - defender->slow_down( roll_dice(1, 3) ); + defender->slow_down( attacker, roll_dice(1, 3) ); } } @@ -4440,7 +4440,7 @@ void melee_attack::mons_apply_attack_flavour(const mon_attack_def &attk) if (one_chance_in(10) || (damage_done > 2 && one_chance_in(3))) { - defender->confuse(1 + random2(3 + atk->hit_dice)); + defender->confuse(attacker, 1 + random2(3 + atk->hit_dice)); } break; diff --git a/crawl-ref/source/it_use2.cc b/crawl-ref/source/it_use2.cc index 16ba9dfdd4..2c3714ae77 100644 --- a/crawl-ref/source/it_use2.cc +++ b/crawl-ref/source/it_use2.cc @@ -217,7 +217,8 @@ bool potion_effect( potion_type pot_eff, int pow, bool was_known ) break; case POT_PARALYSIS: - you.paralyse((2 + random2( 6 + you.duration[DUR_PARALYSIS] )) / factor); + you.paralyse(NULL, + (2 + random2( 6 + you.duration[DUR_PARALYSIS] )) / factor); xom_is_stimulated(64 / factor); break; diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 1435023650..4f7e80b8cf 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -5663,27 +5663,27 @@ void monsters::rot(actor *agent, int rotlevel, int immed_rot) } } -void monsters::confuse(int strength) +void monsters::confuse(actor *atk, int strength) { - enchant_monster_with_flavour(this, BEAM_CONFUSION, strength); + enchant_monster_with_flavour(this, atk, BEAM_CONFUSION, strength); } -void monsters::paralyse(int strength) +void monsters::paralyse(actor *atk, int strength) { - enchant_monster_with_flavour(this, BEAM_PARALYSIS, strength); + enchant_monster_with_flavour(this, atk, BEAM_PARALYSIS, strength); } -void monsters::petrify(int strength) +void monsters::petrify(actor *atk, int strength) { if (mons_is_insubstantial(type)) return; - enchant_monster_with_flavour(this, BEAM_PETRIFY, strength); + enchant_monster_with_flavour(this, atk, BEAM_PETRIFY, strength); } -void monsters::slow_down(int strength) +void monsters::slow_down(actor *atk, int strength) { - enchant_monster_with_flavour(this, BEAM_SLOW, strength); + enchant_monster_with_flavour(this, atk, BEAM_SLOW, strength); } void monsters::set_ghost(const ghost_demon &g) @@ -5986,6 +5986,17 @@ bool monsters::add_ench(const mon_enchant &ench) return (true); } +void monsters::forget_random_spell() +{ + int which_spell = -1; + int count = 0; + for (int i = 0; i < NUM_MONSTER_SPELL_SLOTS; ++i) + if (spells[i] != SPELL_NO_SPELL && one_chance_in(++count)) + which_spell = i; + if (which_spell != -1) + spells[which_spell] = SPELL_NO_SPELL; +} + void monsters::add_enchantment_effect(const mon_enchant &ench, bool quiet) { // Check for slow/haste. @@ -7512,12 +7523,12 @@ item_type_id_state_type monsters::drink_potion_effect(potion_type ptype) break; case POT_SPEED: - if (enchant_monster_with_flavour(this, BEAM_HASTE)) + if (enchant_monster_with_flavour(this, this, BEAM_HASTE)) ident = ID_KNOWN_TYPE; break; case POT_INVISIBILITY: - if (enchant_monster_with_flavour(this, BEAM_INVISIBILITY)) + if (enchant_monster_with_flavour(this, this, BEAM_INVISIBILITY)) ident = ID_KNOWN_TYPE; break; diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index 795b825621..6fc5625818 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -6556,7 +6556,7 @@ static void _handle_monster_move(int i, monsters *monster) } } - if (mons_is_lurking(monster)) + if (mons_is_lurking(monster) || mons_is_submerged(monster)) { // Lurking monsters only stop lurking if their target is right // next to them, otherwise they just sit there. diff --git a/crawl-ref/source/mstuff2.cc b/crawl-ref/source/mstuff2.cc index ecdfc8e4ca..a2276bac09 100644 --- a/crawl-ref/source/mstuff2.cc +++ b/crawl-ref/source/mstuff2.cc @@ -24,6 +24,7 @@ #include "itemname.h" #include "itemprop.h" #include "items.h" +#include "Kills.h" #include "message.h" #include "misc.h" #include "monplace.h" @@ -2237,7 +2238,8 @@ static int _monster_abjuration(const monsters *caster, bool actual) bool silver_statue_effects(monsters *mons) { - if ((mons_player_visible(mons) || one_chance_in(3)) && !one_chance_in(3)) + actor *foe = mons->get_foe(); + if (foe && mons->can_see(foe) && !one_chance_in(3)) { const std::string msg = "'s eyes glow " + weird_glowing_colour() + '.'; @@ -2247,7 +2249,7 @@ bool silver_statue_effects(monsters *mons) mgen_data( summon_any_demon((coinflip() ? DEMON_COMMON : DEMON_LESSER)), - BEH_HOSTILE, 5, you.pos(), MHITYOU)); + BEH_HOSTILE, 5, foe->pos(), MHITYOU)); return (true); } return (false); @@ -2255,12 +2257,21 @@ bool silver_statue_effects(monsters *mons) bool orange_statue_effects(monsters *mons) { - if ((mons_player_visible(mons) || one_chance_in(3)) - && !one_chance_in(3)) + actor *foe = mons->get_foe(); + if (foe && mons->can_see(foe) && !one_chance_in(3)) { - mpr("A hostile presence attacks your mind!", MSGCH_WARN); + if (you.can_see(foe)) + { + if (foe == &you) + mprf(MSGCH_WARN, "A hostile presence attacks your mind!"); + else if (you.can_see(mons)) + mprf(MSGCH_WARN, "%s fixes %s piercing gaze on %s.", + mons->name(DESC_CAP_THE).c_str(), + mons->pronoun(PRONOUN_NOCAP_POSSESSIVE).c_str(), + foe->name(DESC_NOCAP_THE).c_str()); + } - MiscastEffect( &you, monster_index(mons), SPTYP_DIVINATION, + MiscastEffect( foe, monster_index(mons), SPTYP_DIVINATION, random2(15), random2(150), "an orange crystal statue"); return (true); diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index cc236f217a..f04a9e4094 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -6827,12 +6827,12 @@ void player::rot(actor *who, int rotlevel, int immed_rot) disease_player( 50 + random2(100) ); } -void player::confuse(int str) +void player::confuse(actor *who, int str) { confuse_player(str); } -void player::paralyse(int str) +void player::paralyse(actor *who, int str) { int ¶lysis(duration[DUR_PARALYSIS]); @@ -6846,7 +6846,7 @@ void player::paralyse(int str) paralysis = 13; } -void player::petrify(int str) +void player::petrify(actor *who, int str) { int &petrif(duration[DUR_PETRIFIED]); @@ -6859,7 +6859,7 @@ void player::petrify(int str) petrif = std::min(13, petrif); } -void player::slow_down(int str) +void player::slow_down(actor *foe, int str) { ::slow_player( str ); } diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 2ca8d4d9b4..c1e1845971 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -4145,7 +4145,7 @@ static bool _zin_retribution() you.put_to_sleep(); break; case 2: - you.paralyse(3 + random2(10)); + you.paralyse(NULL, 3 + random2(10)); break; } break; diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc index d448f053c5..2623db1db4 100644 --- a/crawl-ref/source/spl-cast.cc +++ b/crawl-ref/source/spl-cast.cc @@ -2461,8 +2461,10 @@ void MiscastEffect::do_miscast() // killed a target which was alive when the object was created. if (!target->alive()) { +#ifdef DEBUG_DIAGNOSTICS mprf(MSGCH_DIAGNOSTICS, "Miscast target '%s' already dead", target->name(DESC_PLAIN, true).c_str()); +#endif return; } @@ -2484,13 +2486,8 @@ void MiscastEffect::do_miscast() sp_type = school; if (sp_type == SPTYP_RANDOM) { - // XXX: Monsters currently have no divination miscasts. - do - { - int exp = (random2(SPTYP_LAST_EXPONENT)); - sp_type = (spschool_flag_type) (1 << exp); - } while (sp_type == SPTYP_DIVINATION - && target->atype() == ACT_MONSTER); + int exp = (random2(SPTYP_LAST_EXPONENT)); + sp_type = (spschool_flag_type) (1 << exp); } } @@ -2788,13 +2785,13 @@ void MiscastEffect::_potion_effect(int pot_eff, int pot_pow) } // Intentional fallthrough if that didn't work. case POT_SLOWING: - target->slow_down(pot_pow); + target->slow_down(act_source, pot_pow); break; case POT_PARALYSIS: - target->paralyse(pot_pow); + target->paralyse(act_source, pot_pow); break; case POT_CONFUSION: - target->confuse(pot_pow); + target->confuse(act_source, pot_pow); break; default: @@ -3662,6 +3659,42 @@ void MiscastEffect::_divination_you(int severity) // XXX: Monster divination miscasts. void MiscastEffect::_divination_mon(int severity) { + switch (severity) + { + case 0: // just a harmless message + mon_msg_seen = "@The_monster@ looks momentarily confused."; + break; + + case 1: // more annoying things + switch (random2(2)) + { + case 0: + mon_msg_seen = "@The_monster@ looks slightly disoriented."; + break; + case 1: + mon_target->confuse( + act_source, + 1 + random2(3 + act_source->get_experience_level())); + break; + } + break; + + case 2: // even more annoying things + mon_msg_seen = "@The_monster@ shudders."; + mon_target->confuse( + act_source, + 5 + random2(3 + act_source->get_experience_level())); + break; + + case 3: // nasty + mon_msg_seen = "@The_monster@ reels."; + if (one_chance_in(7)) + mon_target->forget_random_spell(); + mon_target->confuse( + act_source, + 8 + random2(3 + act_source->get_experience_level())); + break; + } } void MiscastEffect::_necromancy(int severity) |