From 0cebeb433d68aea197f5ee1d2c38809b71c2e3dd Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sat, 19 Dec 2009 22:51:57 +0100 Subject: Iskenderun's Orb of Destruction --- crawl-ref/source/beam.cc | 18 ++++- crawl-ref/source/enum.h | 6 +- crawl-ref/source/fight.cc | 3 +- crawl-ref/source/main.cc | 2 +- crawl-ref/source/makefile.obj | 1 + crawl-ref/source/mgen_data.h | 2 +- crawl-ref/source/mon-act.cc | 16 ++++ crawl-ref/source/mon-data.h | 13 +++ crawl-ref/source/mon-project.cc | 172 ++++++++++++++++++++++++++++++++++++++++ crawl-ref/source/mon-project.h | 17 ++++ crawl-ref/source/mon-util.cc | 3 +- crawl-ref/source/spl-book.cc | 2 +- crawl-ref/source/spl-cast.cc | 8 ++ crawl-ref/source/spl-data.h | 13 +++ 14 files changed, 268 insertions(+), 8 deletions(-) create mode 100644 crawl-ref/source/mon-project.cc create mode 100644 crawl-ref/source/mon-project.h diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index affd03ce5a..c887250051 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -1357,7 +1357,23 @@ const zap_info zap_data[] = { false, false, 0 - } + }, + + { + ZAP_IOOD, + "0", + 200, + NULL, + new tohit_calculator, + WHITE, + false, + BEAM_NUKE, + DCHAR_FIRED_ZAP, + true, + true, + false, + 0 + }, }; static void _zappy(zap_type z_type, int power, bolt &pbolt) diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index 94d2b6328d..fe079d395f 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -1671,8 +1671,8 @@ enum monster_type // (int) menv[].type MONS_KOBOLD_DEMONOLOGIST, MONS_ORC_WIZARD, MONS_ORC_KNIGHT, // 55 - //MONS_WORM_TAIL = 56, // deprecated and now officially removed {dlb} - MONS_WYVERN = 57, // 57 + MONS_ORB_OF_DESTRUCTION, // a projectile, not a real mon + MONS_WYVERN, MONS_BIG_KOBOLD, MONS_GIANT_EYEBALL, MONS_WIGHT, // 60 @@ -2912,6 +2912,7 @@ enum spell_type SPELL_BLINK_CLOSE, SPELL_BLINK_RANGE, SPELL_BLINK_AWAY, + SPELL_IOOD, NUM_SPELLS }; @@ -3159,6 +3160,7 @@ enum zap_type ZAP_SLIME, ZAP_PORKALATOR, ZAP_SLEEP, + ZAP_IOOD, NUM_ZAPS }; diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index 3c349e283c..dc1410a5a6 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -4306,7 +4306,8 @@ bool melee_attack::mons_attack_mons() bool melee_attack::mons_self_destructs() { if (attacker->id() == MONS_GIANT_SPORE - || attacker->id() == MONS_BALL_LIGHTNING) + || attacker->id() == MONS_BALL_LIGHTNING + || attacker->id() == MONS_ORB_OF_DESTRUCTION) { attacker_as_monster()->hit_points = -1; // Do the explosion right now. diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc index d3feb08c00..2a68a7f624 100644 --- a/crawl-ref/source/main.cc +++ b/crawl-ref/source/main.cc @@ -4618,7 +4618,7 @@ static void _compile_time_asserts() COMPILE_CHECK(SP_VAMPIRE == 30 , c3); COMPILE_CHECK(SPELL_DEBUGGING_RAY == 103 , c4); COMPILE_CHECK(SPELL_RETURNING_AMMUNITION == 162 , c5); - COMPILE_CHECK(NUM_SPELLS == 211 , c6); + COMPILE_CHECK(NUM_SPELLS == 212 , c6); //jmf: NEW ASSERTS: we ought to do a *lot* of these COMPILE_CHECK(NUM_SPECIES < SP_UNKNOWN , c7); diff --git a/crawl-ref/source/makefile.obj b/crawl-ref/source/makefile.obj index fd38cf9783..633a9d2a54 100644 --- a/crawl-ref/source/makefile.obj +++ b/crawl-ref/source/makefile.obj @@ -112,6 +112,7 @@ mon-movetarget.o \ mon-pathfind.o \ mon-pick.o \ mon-place.o \ +mon-project.o \ mon-util.o \ mon-speak.o \ mon-stuff.o \ diff --git a/crawl-ref/source/mgen_data.h b/crawl-ref/source/mgen_data.h index 6934100ede..d2794796ec 100644 --- a/crawl-ref/source/mgen_data.h +++ b/crawl-ref/source/mgen_data.h @@ -132,7 +132,7 @@ struct mgen_data non_actor_summoner(nas), props() { ASSERT(summon_type == 0 || (abj >= 1 && abj <= 6) - || mt == MONS_BALL_LIGHTNING); + || mt == MONS_BALL_LIGHTNING || mt == MONS_ORB_OF_DESTRUCTION); } bool permit_bands() const { return (flags & MG_PERMIT_BANDS); } diff --git a/crawl-ref/source/mon-act.cc b/crawl-ref/source/mon-act.cc index 16c025e217..a3a46955ce 100644 --- a/crawl-ref/source/mon-act.cc +++ b/crawl-ref/source/mon-act.cc @@ -33,6 +33,7 @@ #include "mon-cast.h" #include "mon-iter.h" #include "mon-place.h" +#include "mon-project.h" #include "mgen_data.h" #include "coord.h" #include "mon-stuff.h" @@ -1708,6 +1709,14 @@ static void _handle_monster_move(monsters *monster) } old_energy = monster->speed_increment; + if (mons_is_projectile(monster->type)) + { + if (iood_act(*monster)) + return; + monster->lose_energy(EUT_MOVE); + continue; + } + monster->shield_blocks = 0; cloud_type cl_type; @@ -3416,6 +3425,13 @@ static bool _monster_move(monsters *monster) 2 + random2(3), monster->kill_alignment(), KILL_MON_MISSILE ); } + + if (monster->type == MONS_ORB_OF_DESTRUCTION) + { + place_cloud( CLOUD_TLOC_ENERGY, monster->pos(), + 2 + random2(3), monster->kill_alignment(), + KILL_MON_MISSILE ); + } } else { diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h index e9094329bd..c9f8f8d90d 100644 --- a/crawl-ref/source/mon-data.h +++ b/crawl-ref/source/mon-data.h @@ -4283,6 +4283,19 @@ static monsterentry mondata[] = { MONUSE_NOTHING, MONEAT_NOTHING, SIZE_LITTLE }, +{ + MONS_ORB_OF_DESTRUCTION, '*', WHITE, "orb of destruction", + M_INSUBSTANTIAL | M_GLOWS | M_NO_EXP_GAIN, + mrd(MR_RES_FIRE | MR_RES_HELLFIRE | MR_RES_POISON | MR_RES_COLD, 3) + | MR_RES_ELEC | MR_RES_STICKY_FLAME | MR_RES_ACID, + 0, 0, MONS_ORB_OF_DESTRUCTION, MONS_ORB_OF_DESTRUCTION, MH_NONLIVING, MAG_IMMUNE, + { AT_NO_ATK, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, + { 5, 0, 0, 50 }, + 0, 10, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, + I_PLANT, HT_LAND, FL_LEVITATE, 30, DEFAULT_ENERGY, + MONUSE_NOTHING, MONEAT_NOTHING, SIZE_LITTLE +}, + // other symbols { MONS_VAPOUR, '#', LIGHTGREY, "vapour", diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc new file mode 100644 index 0000000000..0052055d2a --- /dev/null +++ b/crawl-ref/source/mon-project.cc @@ -0,0 +1,172 @@ +/* + * File: mon-project.cc + * Summary: Slow projectiles, done as monsters. + * Written by: Adam Borowski + */ + +#include "AppHdr.h" + +#include "mon-project.h" + +#include +#include +#include +#include + +#include "externs.h" + +#include "coord.h" +#include "env.h" +#include "mgen_data.h" +#include "mon-place.h" +#include "mon-stuff.h" +#include "stuff.h" +#include "terrain.h" +#include "viewchar.h" + +bool mons_is_projectile(monster_type mt) +{ + return (mt == MONS_ORB_OF_DESTRUCTION); +} + +bool cast_iood(actor *caster, int pow, bolt *beam) +{ + int mtarg = mgrd(beam->target); + + int mind = mons_place(mgen_data(MONS_ORB_OF_DESTRUCTION, + (caster->atype() == ACT_PLAYER) ? BEH_FRIENDLY : + ((monsters*)caster)->wont_attack() ? BEH_FRIENDLY : BEH_HOSTILE, + caster, + 0, + SPELL_IOOD, + coord_def(-1, -1), + (mtarg != NON_MONSTER) ? mtarg : + (you.pos() == beam->target) ? MHITYOU : MHITNOT, + 0, + GOD_NO_GOD)); + if (mind == -1) + { + canned_msg(MSG_NOTHING_HAPPENS); + return (false); + } + + monsters &mon = menv[mind]; + const coord_def pos = caster->pos(); + mon.props["iood_x"] = (float)pos.x; + mon.props["iood_y"] = (float)pos.y; + mon.props["iood_vx"] = (float)(beam->target.x - pos.x); + mon.props["iood_vy"] = (float)(beam->target.y - pos.y); + mon.props["iood_kc"].get_byte() = (caster->atype() == ACT_PLAYER) ? KC_YOU : + ((monsters*)caster)->wont_attack() ? KC_FRIENDLY : KC_OTHER; + mon.flags &= ~MF_JUST_SUMMONED; + + // Move away from the caster's square. + iood_act(mon); + mon.lose_energy(EUT_MOVE); + return (true); +} + +void _normalize(float &x, float &y) +{ + const float d = sqrt(x*x + y*y); + if (d <= 0.000001) + return; + x/=d; + y/=d; +} + +void _iood_dissipate(monsters &mon) +{ + simple_monster_message(&mon, " dissipates."); + mpr("iood: dissipating"); + monster_die(&mon, KILL_DISMISSED, NON_MONSTER); +} + +bool _iood_hit(monsters &mon, const coord_def &pos) +{ + bolt beam; + beam.name = "orb of destruction"; + beam.flavour = BEAM_NUKE; + beam.attitude = mon.attitude; + beam.thrower = (mon.props["iood_kc"].get_byte() == KC_YOU) + ? KILL_YOU_MISSILE : KILL_MON_MISSILE; + beam.colour = WHITE; + beam.type = dchar_glyph(DCHAR_FIRED_BURST); + beam.range = 1; + beam.source = pos; + beam.target = pos; + beam.hit = AUTOMATIC_HIT; + beam.damage = dice_def(3, 20); + beam.fire(); + + return (true); +} + +// returns true if the orb is gone +bool iood_act(monsters &mon) +{ + ASSERT(mons_is_projectile(mon.type)); + + float x = mon.props["iood_x"]; + float y = mon.props["iood_y"]; + float vx = mon.props["iood_vx"]; + float vy = mon.props["iood_vy"]; + + mprf("iood_act: pos (%d,%d) rpos (%f,%f) v (%f,%f)", mon.pos().x, mon.pos().y, + x, y, vx, vy); + + if (!vx && !vy) // not initialized + { + _iood_dissipate(mon); + return (true); + } + + coord_def target(-1, -1); + if (mon.foe == MHITYOU) + target = you.pos(); + else if (invalid_monster_index(mon.foe)) + ; + else if (invalid_monster_type(menv[mon.foe].type)) + { + // Our target is gone. Since picking a new one would require + // intelligence, the orb continues on a ballistic course. + mon.foe = MHITNOT; + } + else + target = menv[mon.foe].pos(); + + _normalize(vx, vy); + + x += vx; + y += vy; + + mon.props["iood_x"] = x; + mon.props["iood_y"] = y; + + coord_def pos(round(x), round(y)); + if (!in_bounds(pos)) + { + _iood_dissipate(mon); + return (true); + } + + if (pos == mon.pos()) + return (false); + + if (cell_is_solid(pos) || actor_at(pos)) + { + if (_iood_hit(mon, pos)) + { + monster_die(&mon, KILL_DISMISSED, NON_MONSTER); + return (true); + } + } + + if (!mon.move_to_pos(pos)) + { + _iood_dissipate(mon); + return (true); + } + + return (false); +} diff --git a/crawl-ref/source/mon-project.h b/crawl-ref/source/mon-project.h new file mode 100644 index 0000000000..3f17a9c755 --- /dev/null +++ b/crawl-ref/source/mon-project.h @@ -0,0 +1,17 @@ +/* + * File: mon-project.cc + * Summary: Slow projectiles, done as monsters. + * Written by: Adam Borowski + */ + +#ifndef MON_PROJECT_H +#define MON_PROJECT_H + +#include "beam.h" + +bool mons_is_projectile(monster_type mt); + +bool cast_iood(actor *caster, int pow, bolt *beam); +bool iood_act(monsters &mon); + +#endif diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 9420d1d78c..17ed88bd8e 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -2010,7 +2010,8 @@ bool mons_wields_two_weapons(const monsters *mon) bool mons_self_destructs(const monsters *m) { - return (m->type == MONS_GIANT_SPORE || m->type == MONS_BALL_LIGHTNING); + return (m->type == MONS_GIANT_SPORE || m->type == MONS_BALL_LIGHTNING + || m->type == MONS_ORB_OF_DESTRUCTION); } int mons_base_damage_brand(const monsters *m) diff --git a/crawl-ref/source/spl-book.cc b/crawl-ref/source/spl-book.cc index f5f89f44b6..d5810bc106 100644 --- a/crawl-ref/source/spl-book.cc +++ b/crawl-ref/source/spl-book.cc @@ -518,12 +518,12 @@ static spell_type spellbook_template_array[][SPELLBOOK_SIZE] = // Book of Annihilations - Vehumet special {SPELL_ISKENDERUNS_MYSTIC_BLAST, SPELL_POISON_ARROW, + SPELL_IOOD, SPELL_CHAIN_LIGHTNING, SPELL_LEHUDIBS_CRYSTAL_SPEAR, SPELL_ICE_STORM, SPELL_FIRE_STORM, SPELL_NO_SPELL, - SPELL_NO_SPELL, }, // Book of Demonology - Vehumet special diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc index e35944c8ce..efb8386ee0 100644 --- a/crawl-ref/source/spl-cast.cc +++ b/crawl-ref/source/spl-cast.cc @@ -37,6 +37,7 @@ #include "message.h" #include "mon-cast.h" #include "mon-place.h" +#include "mon-project.h" #include "mon-stuff.h" #include "mutation.h" #include "ouch.h" @@ -1514,6 +1515,13 @@ spret_type your_spells(spell_type spell, int powc, bool allow_fail) return (SPRET_ABORT); break; + case SPELL_IOOD: + if (!player_tracer(ZAP_IOOD, powc, beam)) + return (SPRET_ABORT); + if (!cast_iood(&you, powc, &beam)) + return (SPRET_ABORT); + break; + // Clouds and explosions. case SPELL_MEPHITIC_CLOUD: if (!stinking_cloud(powc, beam)) diff --git a/crawl-ref/source/spl-data.h b/crawl-ref/source/spl-data.h index 27f1ea2632..cd0e4336d8 100644 --- a/crawl-ref/source/spl-data.h +++ b/crawl-ref/source/spl-data.h @@ -2589,6 +2589,19 @@ true }, +{ + SPELL_IOOD, "Iskenderun's Orb of Destruction", + SPTYP_CONJURATION, + SPFLAG_DIR_OR_TARGET, + 7, + 200, + 9, 9, + 0, + NULL, + true, + false +}, + { SPELL_NO_SPELL, "nonexistent spell", 0, -- cgit v1.2.3-54-g00ecf From 8e45c6edf11d3c293961ca9938467ed91c1a340c Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sat, 19 Dec 2009 16:36:28 +0100 Subject: Make debug messages show only in debug builds. --- crawl-ref/source/mon-project.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index 0052055d2a..cb37776c61 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -78,7 +78,9 @@ void _normalize(float &x, float &y) void _iood_dissipate(monsters &mon) { simple_monster_message(&mon, " dissipates."); - mpr("iood: dissipating"); +#ifdef DEBUG_DIAGNOSTICS + mprf(MSGCH_DIAGNOSTICS, "iood: dissipating"); +#endif monster_die(&mon, KILL_DISMISSED, NON_MONSTER); } @@ -112,8 +114,12 @@ bool iood_act(monsters &mon) float vx = mon.props["iood_vx"]; float vy = mon.props["iood_vy"]; - mprf("iood_act: pos (%d,%d) rpos (%f,%f) v (%f,%f)", mon.pos().x, mon.pos().y, - x, y, vx, vy); +#ifdef DEBUG_DIAGNOSTICS + mprf(MSGCH_DIAGNOSTICS, + "iood_act: pos (%d,%d) rpos (%f,%f) v (%f,%f)", + mon.pos().x, mon.pos().y, + x, y, vx, vy); +#endif if (!vx && !vy) // not initialized { -- cgit v1.2.3-54-g00ecf From 75cf943abb6e77df046924a0f6946c21c5798862 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sat, 19 Dec 2009 22:52:31 +0100 Subject: Tloc smoke trail. Doesn't look good IMO, I'd replace it with normal transparent smoke. --- crawl-ref/source/mon-act.cc | 7 ------- crawl-ref/source/mon-project.cc | 12 ++++++++++-- crawl-ref/source/mon-project.h | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/crawl-ref/source/mon-act.cc b/crawl-ref/source/mon-act.cc index a3a46955ce..62df9c963b 100644 --- a/crawl-ref/source/mon-act.cc +++ b/crawl-ref/source/mon-act.cc @@ -3425,13 +3425,6 @@ static bool _monster_move(monsters *monster) 2 + random2(3), monster->kill_alignment(), KILL_MON_MISSILE ); } - - if (monster->type == MONS_ORB_OF_DESTRUCTION) - { - place_cloud( CLOUD_TLOC_ENERGY, monster->pos(), - 2 + random2(3), monster->kill_alignment(), - KILL_MON_MISSILE ); - } } else { diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index cb37776c61..4fd4583fe3 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -15,6 +15,7 @@ #include "externs.h" +#include "cloud.h" #include "coord.h" #include "env.h" #include "mgen_data.h" @@ -61,7 +62,7 @@ bool cast_iood(actor *caster, int pow, bolt *beam) mon.flags &= ~MF_JUST_SUMMONED; // Move away from the caster's square. - iood_act(mon); + iood_act(mon, true); mon.lose_energy(EUT_MOVE); return (true); } @@ -105,7 +106,7 @@ bool _iood_hit(monsters &mon, const coord_def &pos) } // returns true if the orb is gone -bool iood_act(monsters &mon) +bool iood_act(monsters &mon, bool no_trail) { ASSERT(mons_is_projectile(mon.type)); @@ -168,6 +169,13 @@ bool iood_act(monsters &mon) } } + if (!no_trail) + { + place_cloud(CLOUD_TLOC_ENERGY, mon.pos(), + 2 + random2(3), mon.kill_alignment(), + KILL_MON_MISSILE); + } + if (!mon.move_to_pos(pos)) { _iood_dissipate(mon); diff --git a/crawl-ref/source/mon-project.h b/crawl-ref/source/mon-project.h index 3f17a9c755..a57afbbd80 100644 --- a/crawl-ref/source/mon-project.h +++ b/crawl-ref/source/mon-project.h @@ -12,6 +12,6 @@ bool mons_is_projectile(monster_type mt); bool cast_iood(actor *caster, int pow, bolt *beam); -bool iood_act(monsters &mon); +bool iood_act(monsters &mon, bool no_trail = false); #endif -- cgit v1.2.3-54-g00ecf From b161ada09adaa9728967067c874e4636817318ce Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sat, 19 Dec 2009 22:12:26 +0100 Subject: Announce when an iood hits a wall. --- crawl-ref/source/mon-project.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index 4fd4583fe3..8f061a30d0 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -16,6 +16,7 @@ #include "externs.h" #include "cloud.h" +#include "directn.h" #include "coord.h" #include "env.h" #include "mgen_data.h" @@ -162,6 +163,12 @@ bool iood_act(monsters &mon, bool no_trail) if (cell_is_solid(pos) || actor_at(pos)) { + if (cell_is_solid(pos)) + { + simple_monster_message(&mon, (" hits " + feature_description(pos, + false, DESC_NOCAP_A)).c_str()); + } + if (_iood_hit(mon, pos)) { monster_die(&mon, KILL_DISMISSED, NON_MONSTER); -- cgit v1.2.3-54-g00ecf From 38abbd0d71c61f16c6d13a4107c61fb639a00f92 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sat, 19 Dec 2009 22:35:31 +0100 Subject: When two orbs collide, make a big boom! --- crawl-ref/source/mon-project.cc | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index 8f061a30d0..bc3e385e42 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -22,6 +22,7 @@ #include "mgen_data.h" #include "mon-place.h" #include "mon-stuff.h" +#include "shout.h" #include "stuff.h" #include "terrain.h" #include "viewchar.h" @@ -86,7 +87,7 @@ void _iood_dissipate(monsters &mon) monster_die(&mon, KILL_DISMISSED, NON_MONSTER); } -bool _iood_hit(monsters &mon, const coord_def &pos) +bool _iood_hit(monsters &mon, const coord_def &pos, bool big_boom = false) { bolt beam; beam.name = "orb of destruction"; @@ -101,8 +102,13 @@ bool _iood_hit(monsters &mon, const coord_def &pos) beam.target = pos; beam.hit = AUTOMATIC_HIT; beam.damage = dice_def(3, 20); - beam.fire(); + beam.ex_size = 1; + if (big_boom) + beam.explode(true, true); + else + beam.fire(); + monster_die(&mon, KILL_DISMISSED, NON_MONSTER); return (true); } @@ -161,19 +167,27 @@ bool iood_act(monsters &mon, bool no_trail) if (pos == mon.pos()) return (false); - if (cell_is_solid(pos) || actor_at(pos)) + actor *victim = actor_at(pos); + if (cell_is_solid(pos) || victim) { if (cell_is_solid(pos)) { simple_monster_message(&mon, (" hits " + feature_description(pos, false, DESC_NOCAP_A)).c_str()); } - - if (_iood_hit(mon, pos)) + if (victim && mons_is_projectile(victim->id())) { - monster_die(&mon, KILL_DISMISSED, NON_MONSTER); + if (mon.observable()) + mpr("The orbs collide in a blinding explosion!"); + else + noisy(40, pos, "You hear a loud magical explosion!"); + monster_die((monsters*)victim, KILL_DISMISSED, NON_MONSTER); + _iood_hit(mon, pos, true); return (true); } + + if (_iood_hit(mon, pos)) + return (true); } if (!no_trail) -- cgit v1.2.3-54-g00ecf From 7db74e3bb5838dc8690e8660a138f69f2895ba86 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sat, 19 Dec 2009 22:42:00 +0100 Subject: Fix visibility for hitting a wall just out of LOS. --- crawl-ref/source/mon-project.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index bc3e385e42..4a080a43fd 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -172,8 +172,9 @@ bool iood_act(monsters &mon, bool no_trail) { if (cell_is_solid(pos)) { - simple_monster_message(&mon, (" hits " + feature_description(pos, - false, DESC_NOCAP_A)).c_str()); + if (you.see_cell(pos)) + mprf("%s hits %s", mon.name(DESC_CAP_THE, true).c_str(), + feature_description(pos, false, DESC_NOCAP_A).c_str()); } if (victim && mons_is_projectile(victim->id())) { -- cgit v1.2.3-54-g00ecf From 2425ac2d2faab70cd993d56aa7610d9cd1ff7d8f Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sat, 19 Dec 2009 22:44:37 +0100 Subject: Disallow targetting self. --- crawl-ref/source/spl-data.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/spl-data.h b/crawl-ref/source/spl-data.h index cd0e4336d8..52a94a8786 100644 --- a/crawl-ref/source/spl-data.h +++ b/crawl-ref/source/spl-data.h @@ -2592,7 +2592,7 @@ { SPELL_IOOD, "Iskenderun's Orb of Destruction", SPTYP_CONJURATION, - SPFLAG_DIR_OR_TARGET, + SPFLAG_DIR_OR_TARGET | SPFLAG_NOT_SELF, 7, 200, 9, 9, -- cgit v1.2.3-54-g00ecf From 198cb7cf6376840927d897c24c5ab2bec36b4739 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sat, 19 Dec 2009 23:03:17 +0100 Subject: Stop tracers from complaining about the previous orb. Also, make them imprevious to disintegration -- should we explode instead? --- crawl-ref/source/beam.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index c887250051..a37fe4b70d 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -6028,6 +6028,12 @@ bool bolt::nasty_to(const monsters *mon) const if (flavour == BEAM_HOLY) return (mon->res_holy_energy(agent()) <= 0); + // The orbs are made of pure disintegration energy. This also has the side + // effect of not stopping us from firing further orbs when the previous one + // is still flying. + if (flavour == BEAM_DISINTEGRATION || flavour == BEAM_NUKE) + return (mon->type != MONS_ORB_OF_DESTRUCTION); + // Take care of other non-enchantments. if (!is_enchantment()) return (true); -- cgit v1.2.3-54-g00ecf From 85138818b78fbeec60ef96a72f8fa5ba05034274 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sun, 20 Dec 2009 01:32:57 +0100 Subject: IOOD as a monster spell. --- crawl-ref/source/dat/database/monspell.txt | 8 ++++++++ crawl-ref/source/mon-cast.cc | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/crawl-ref/source/dat/database/monspell.txt b/crawl-ref/source/dat/database/monspell.txt index 0ce22a12e5..ce3a29d30e 100644 --- a/crawl-ref/source/dat/database/monspell.txt +++ b/crawl-ref/source/dat/database/monspell.txt @@ -92,6 +92,14 @@ Symbol of Torment cast unseen Symbol of Torment cast @The_something@ calls on the powers of Hell! +%%%% +Iskenderun's Orb of Destruction cast + +@The_monster@ conjures a glowing orb. + +@The_monster@ conjures an orb of pure magic. + +@The_monster@ launches a ball of destructive magic. ##################################################### # Individual innate spells (breathing and spitting). ##################################################### diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc index ba5982b8c4..25864af558 100644 --- a/crawl-ref/source/mon-cast.cc +++ b/crawl-ref/source/mon-cast.cc @@ -20,6 +20,7 @@ #include "mon-behv.h" #include "mon-iter.h" #include "mon-place.h" +#include "mon-project.h" #include "terrain.h" #include "mgen_data.h" #include "coord.h" @@ -669,6 +670,11 @@ bolt mons_spells( monsters *mons, spell_type spell_cast, int power, beam.is_beam = true; break; + case SPELL_IOOD: // tracer only + beam.flavour = BEAM_NUKE; + beam.is_beam = true; + break; + default: if (check_validity) { @@ -2171,6 +2177,9 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast, monster->foe, 0, god)); } return; + case SPELL_IOOD: + cast_iood(monster, 6 * monster->hit_dice, &pbolt); + return; } // If a monster just came into view and immediately cast a spell, -- cgit v1.2.3-54-g00ecf From 76442a6a837472a0909ad49e6a118184b90777d4 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sun, 20 Dec 2009 19:04:36 +0100 Subject: Homing. --- crawl-ref/source/mon-project.cc | 59 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index 4a080a43fd..ffcfb8a8a2 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -69,7 +69,7 @@ bool cast_iood(actor *caster, int pow, bolt *beam) return (true); } -void _normalize(float &x, float &y) +static void _normalize(float &x, float &y) { const float d = sqrt(x*x + y*y); if (d <= 0.000001) @@ -78,6 +78,12 @@ void _normalize(float &x, float &y) y/=d; } +// angle measured in chord length +static bool _in_front(float vx, float vy, float dx, float dy, float angle) +{ + return ((dx-vx)*(dx-vx) + (dy-vy)*(dy-vy) <= (angle*angle)); +} + void _iood_dissipate(monsters &mon) { simple_monster_message(&mon, " dissipates."); @@ -112,6 +118,13 @@ bool _iood_hit(monsters &mon, const coord_def &pos, bool big_boom = false) return (true); } +#ifdef DEBUG_DIAGNOSTICS +#define dprf(...) mprf(MSGCH_DIAGNOSTICS, __VA_ARGS__) +#else +static void nada(); +#define dprf(...) nada() +#endif + // returns true if the orb is gone bool iood_act(monsters &mon, bool no_trail) { @@ -151,6 +164,50 @@ bool iood_act(monsters &mon, bool no_trail) _normalize(vx, vy); + if (target != coord_def(-1, -1)) + { + float dx = target.x - x; + float dy = target.y - y; + _normalize(dx, dy); + + // Special case: + // Moving diagonally when the orb is just about to hit you + // 2 + // ->*1 + // (from 1 to 2) would be a guaranteed escape. This may be + // realistic (strafing!), but since the game has no non-cheesy + // means of waiting a small fraction of a turn, we don't want it. + const int old_t_pos = mon.props["iood_tpos"].get_short(); + if (old_t_pos && old_t_pos != (256 * target.x + target.y) + && (coord_def(round(x), round(y)) - target).rdist() <= 1 + // ... but following an orb is ok. + && _in_front(vx, vy, dx, dy, 1.5)) // ~97 degrees + { + vx = dx; + vy = dy; + } + mon.props["iood_tpos"].get_short() = 256 * target.x + target.y; + + if (!_in_front(vx, vy, dx, dy, 0.5)) // ~29 degrees + { + float ax, ay; + if (dy*vx < dx*vy) + ax = vy, ay = -vx, dprf("iood: veering left"); + else + ax = -vy, ay = vx, dprf("iood: veering right"); + mprf(MSGCH_DIAGNOSTICS, "iood: veering %s", (dy*vx < dx*vy) ? + "left" : "right"); + vx += ax * 0.3; + vy += ay * 0.3; + } + else + dprf("iood: keeping course"); + + _normalize(vx, vy); + mon.props["iood_vx"] = vx; + mon.props["iood_vy"] = vy; + } + x += vx; y += vy; -- cgit v1.2.3-54-g00ecf From 32b5cab8cacc2b0b076610486042261d7a9d1fc2 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sun, 20 Dec 2009 22:20:10 +0100 Subject: Make orb-orb explosion prettier. --- crawl-ref/source/mon-project.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index 32259e6b10..7808adb2ab 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -107,12 +107,14 @@ bool _iood_hit(monsters &mon, const coord_def &pos, bool big_boom = false) beam.hit = AUTOMATIC_HIT; beam.damage = dice_def(3, 20); beam.ex_size = 1; + + monster_die(&mon, KILL_DISMISSED, NON_MONSTER); + if (big_boom) - beam.explode(true, true); + beam.explode(true, false); else beam.fire(); - monster_die(&mon, KILL_DISMISSED, NON_MONSTER); return (true); } -- cgit v1.2.3-54-g00ecf From ea22cd80a5344cd61b27cb1246ff741a5c6829c4 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sun, 20 Dec 2009 23:02:35 +0100 Subject: Make the "killing friend" conduct, slouch and swapping place treat projectiles as non-monsters. --- crawl-ref/source/godabil.cc | 2 +- crawl-ref/source/mon-abil.cc | 1 + crawl-ref/source/mon-project.cc | 5 ----- crawl-ref/source/mon-project.h | 2 -- crawl-ref/source/mon-stuff.cc | 7 +++++++ crawl-ref/source/mon-util.cc | 5 +++++ crawl-ref/source/mon-util.h | 2 +- crawl-ref/source/religion.cc | 2 ++ 8 files changed, 17 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/godabil.cc b/crawl-ref/source/godabil.cc index edb1b723fb..4b9150f860 100644 --- a/crawl-ref/source/godabil.cc +++ b/crawl-ref/source/godabil.cc @@ -1256,7 +1256,7 @@ bool ponderousify_armour() static int _slouch_monsters(coord_def where, int pow, int, actor* agent) { monsters* mon = monster_at(where); - if (mon == NULL || mons_is_stationary(mon)) + if (mon == NULL || mons_is_stationary(mon) || mons_is_projectile(mon->type)) return (0); int dmg = (mon->speed - 1000/player_movement_speed()/player_speed()); diff --git a/crawl-ref/source/mon-abil.cc b/crawl-ref/source/mon-abil.cc index 32a764bcb1..7cdf85eaf2 100644 --- a/crawl-ref/source/mon-abil.cc +++ b/crawl-ref/source/mon-abil.cc @@ -494,6 +494,7 @@ static bool _siren_movement_effect(const monsters *monster) coord_def swapdest; if (mon->wont_attack() && !mons_is_stationary(mon) + && !mons_is_projectile(mon->type) && !mon->cannot_act() && !mon->asleep() && swap_check(mon, swapdest, true)) diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index 7808adb2ab..c6e4c18788 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -27,11 +27,6 @@ #include "terrain.h" #include "viewchar.h" -bool mons_is_projectile(monster_type mt) -{ - return (mt == MONS_ORB_OF_DESTRUCTION); -} - bool cast_iood(actor *caster, int pow, bolt *beam) { int mtarg = mgrd(beam->target); diff --git a/crawl-ref/source/mon-project.h b/crawl-ref/source/mon-project.h index a57afbbd80..f10b543097 100644 --- a/crawl-ref/source/mon-project.h +++ b/crawl-ref/source/mon-project.h @@ -9,8 +9,6 @@ #include "beam.h" -bool mons_is_projectile(monster_type mt); - bool cast_iood(actor *caster, int pow, bolt *beam); bool iood_act(monsters &mon, bool no_trail = false); diff --git a/crawl-ref/source/mon-stuff.cc b/crawl-ref/source/mon-stuff.cc index 76f964fe20..974188694a 100644 --- a/crawl-ref/source/mon-stuff.cc +++ b/crawl-ref/source/mon-stuff.cc @@ -2815,6 +2815,13 @@ bool swap_check(monsters *monster, coord_def &loc, bool quiet) return (false); } + if (mons_is_projectile(monster->type)) + { + if (!quiet) + mpr("It's unwise to walk into this."); + return (false); + } + if (monster->caught()) { if (!quiet) diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 17ed88bd8e..3844147b82 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -484,6 +484,11 @@ bool mons_is_fast(const monsters *mon) return (mon->speed > pspeed); } +bool mons_is_projectile(int mc) +{ + return (mc == MONS_ORB_OF_DESTRUCTION); +} + bool mons_is_insubstantial(int mc) { return (mons_class_flag(mc, M_INSUBSTANTIAL)); diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h index b9c5424aee..ce186ddf40 100644 --- a/crawl-ref/source/mon-util.h +++ b/crawl-ref/source/mon-util.h @@ -657,7 +657,7 @@ bool mons_class_is_stationary(int mc); bool mons_is_stationary(const monsters *mon); bool mons_is_fast( const monsters *mon ); - +bool mons_is_projectile(int mc); bool mons_is_insubstantial(int mc); bool mons_has_blood(int mc); diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 3ec55a07cc..68f1541f59 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -4484,6 +4484,8 @@ bool god_hates_attacking_friend(god_type god, const actor *fr) bool god_hates_attacking_friend(god_type god, int species) { + if (mons_is_projectile(species)) + return (false); switch (god) { case GOD_ZIN: -- cgit v1.2.3-54-g00ecf From 96abf90502dcfd130f5f553cf2d231c7d16a1bb4 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sun, 20 Dec 2009 23:11:01 +0100 Subject: Don't trust mon.foe, too many things mess with that. --- crawl-ref/source/mon-project.cc | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index c6e4c18788..c8fe96e9a9 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -30,6 +30,8 @@ bool cast_iood(actor *caster, int pow, bolt *beam) { int mtarg = mgrd(beam->target); + if (you.pos() == beam->target) + mtarg = MHITYOU; int mind = mons_place(mgen_data(MONS_ORB_OF_DESTRUCTION, (caster->atype() == ACT_PLAYER) ? BEH_FRIENDLY : @@ -38,8 +40,7 @@ bool cast_iood(actor *caster, int pow, bolt *beam) 0, SPELL_IOOD, coord_def(-1, -1), - (mtarg != NON_MONSTER) ? mtarg : - (you.pos() == beam->target) ? MHITYOU : MHITNOT, + mtarg, 0, GOD_NO_GOD)); if (mind == -1) @@ -54,6 +55,7 @@ bool cast_iood(actor *caster, int pow, bolt *beam) mon.props["iood_y"] = (float)pos.y; mon.props["iood_vx"] = (float)(beam->target.x - pos.x); mon.props["iood_vy"] = (float)(beam->target.y - pos.y); + mon.props["iood_foe"].get_short() = mtarg; mon.props["iood_kc"].get_byte() = (caster->atype() == ACT_PLAYER) ? KC_YOU : ((monsters*)caster)->wont_attack() ? KC_FRIENDLY : KC_OTHER; mon.flags &= ~MF_JUST_SUMMONED; @@ -134,18 +136,20 @@ bool iood_act(monsters &mon, bool no_trail) } coord_def target(-1, -1); - if (mon.foe == MHITYOU) + int foe = mon.props["iood_foe"].get_short(); + if (foe == MHITYOU) target = you.pos(); - else if (invalid_monster_index(mon.foe)) + else if (invalid_monster_index(foe)) ; - else if (invalid_monster_type(menv[mon.foe].type)) + else if (invalid_monster_type(menv[foe].type)) { // Our target is gone. Since picking a new one would require // intelligence, the orb continues on a ballistic course. - mon.foe = MHITNOT; + foe = MHITNOT; + mon.props["iood_foe"].get_short() = foe; } else - target = menv[mon.foe].pos(); + target = menv[foe].pos(); _normalize(vx, vy); -- cgit v1.2.3-54-g00ecf From 7512f07d9a371554721dfb59ae9993fed1128ac8 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Mon, 21 Dec 2009 01:00:44 +0100 Subject: Actually use spell power. --- crawl-ref/source/mon-project.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index c8fe96e9a9..55010782e9 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -58,6 +58,7 @@ bool cast_iood(actor *caster, int pow, bolt *beam) mon.props["iood_foe"].get_short() = mtarg; mon.props["iood_kc"].get_byte() = (caster->atype() == ACT_PLAYER) ? KC_YOU : ((monsters*)caster)->wont_attack() ? KC_FRIENDLY : KC_OTHER; + mon.props["iood_pow"].get_short() = pow; mon.flags &= ~MF_JUST_SUMMONED; // Move away from the caster's square. @@ -102,7 +103,7 @@ bool _iood_hit(monsters &mon, const coord_def &pos, bool big_boom = false) beam.source = pos; beam.target = pos; beam.hit = AUTOMATIC_HIT; - beam.damage = dice_def(3, 20); + beam.damage = dice_def(6, mon.props["iood_pow"].get_short()/4); beam.ex_size = 1; monster_die(&mon, KILL_DISMISSED, NON_MONSTER); -- cgit v1.2.3-54-g00ecf From c546c371c46b95a99afd87300a28f39318fa6cb3 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Mon, 21 Dec 2009 01:24:56 +0100 Subject: Revert "Don't trust mon.foe, too many things mess with that." --- crawl-ref/source/mon-project.cc | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index 55010782e9..d6eced6085 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -30,8 +30,6 @@ bool cast_iood(actor *caster, int pow, bolt *beam) { int mtarg = mgrd(beam->target); - if (you.pos() == beam->target) - mtarg = MHITYOU; int mind = mons_place(mgen_data(MONS_ORB_OF_DESTRUCTION, (caster->atype() == ACT_PLAYER) ? BEH_FRIENDLY : @@ -40,7 +38,8 @@ bool cast_iood(actor *caster, int pow, bolt *beam) 0, SPELL_IOOD, coord_def(-1, -1), - mtarg, + (mtarg != NON_MONSTER) ? mtarg : + (you.pos() == beam->target) ? MHITYOU : MHITNOT, 0, GOD_NO_GOD)); if (mind == -1) @@ -55,7 +54,6 @@ bool cast_iood(actor *caster, int pow, bolt *beam) mon.props["iood_y"] = (float)pos.y; mon.props["iood_vx"] = (float)(beam->target.x - pos.x); mon.props["iood_vy"] = (float)(beam->target.y - pos.y); - mon.props["iood_foe"].get_short() = mtarg; mon.props["iood_kc"].get_byte() = (caster->atype() == ACT_PLAYER) ? KC_YOU : ((monsters*)caster)->wont_attack() ? KC_FRIENDLY : KC_OTHER; mon.props["iood_pow"].get_short() = pow; @@ -137,20 +135,18 @@ bool iood_act(monsters &mon, bool no_trail) } coord_def target(-1, -1); - int foe = mon.props["iood_foe"].get_short(); - if (foe == MHITYOU) + if (mon.foe == MHITYOU) target = you.pos(); - else if (invalid_monster_index(foe)) + else if (invalid_monster_index(mon.foe)) ; - else if (invalid_monster_type(menv[foe].type)) + else if (invalid_monster_type(menv[mon.foe].type)) { // Our target is gone. Since picking a new one would require // intelligence, the orb continues on a ballistic course. - foe = MHITNOT; - mon.props["iood_foe"].get_short() = foe; + mon.foe = MHITNOT; } else - target = menv[foe].pos(); + target = menv[mon.foe].pos(); _normalize(vx, vy); -- cgit v1.2.3-54-g00ecf From 5b7701dc9d19fdad4de1a64b41995d65c03b7df6 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Mon, 21 Dec 2009 01:43:19 +0100 Subject: Short-circuit behaviour_event(), projectiles are not supposed to behave. --- crawl-ref/source/mon-behv.cc | 2 ++ crawl-ref/source/mon-project.cc | 9 +++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/mon-behv.cc b/crawl-ref/source/mon-behv.cc index aea54df3e6..98a1f3e853 100644 --- a/crawl-ref/source/mon-behv.cc +++ b/crawl-ref/source/mon-behv.cc @@ -680,6 +680,8 @@ void behaviour_event(monsters *mon, mon_event_type event, int src, ASSERT(src >= 0 && src <= MHITYOU); ASSERT(!crawl_state.arena || src != MHITYOU); ASSERT(in_bounds(src_pos) || src_pos.origin()); + if (mons_is_projectile(mon->type)) + return; // projectiles have no AI const beh_type old_behaviour = mon->behaviour; diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index d6eced6085..ffd0eb2c00 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -30,6 +30,8 @@ bool cast_iood(actor *caster, int pow, bolt *beam) { int mtarg = mgrd(beam->target); + if (beam->target == you.pos()) + mtarg = MHITYOU; int mind = mons_place(mgen_data(MONS_ORB_OF_DESTRUCTION, (caster->atype() == ACT_PLAYER) ? BEH_FRIENDLY : @@ -38,8 +40,7 @@ bool cast_iood(actor *caster, int pow, bolt *beam) 0, SPELL_IOOD, coord_def(-1, -1), - (mtarg != NON_MONSTER) ? mtarg : - (you.pos() == beam->target) ? MHITYOU : MHITNOT, + mtarg, 0, GOD_NO_GOD)); if (mind == -1) @@ -124,9 +125,9 @@ bool iood_act(monsters &mon, bool no_trail) float vx = mon.props["iood_vx"]; float vy = mon.props["iood_vy"]; - dprf("iood_act: pos (%d,%d) rpos (%f,%f) v (%f,%f)", + dprf("iood_act: pos=(%d,%d) rpos=(%f,%f) v=(%f,%f) foe=%d", mon.pos().x, mon.pos().y, - x, y, vx, vy); + x, y, vx, vy, mon.foe); if (!vx && !vy) // not initialized { -- cgit v1.2.3-54-g00ecf From 4625fe5165f053cc056149de83331c1618aa01e5 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Wed, 23 Dec 2009 14:13:35 +0100 Subject: Use grey not tloc smoke, iood uses no instant translocations. This departs from the original idea. --- crawl-ref/source/mon-project.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index ffd0eb2c00..d812be7982 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -235,7 +235,7 @@ bool iood_act(monsters &mon, bool no_trail) if (!no_trail) { - place_cloud(CLOUD_TLOC_ENERGY, mon.pos(), + place_cloud(CLOUD_GREY_SMOKE, mon.pos(), 2 + random2(3), mon.kill_alignment(), KILL_MON_MISSILE); } -- cgit v1.2.3-54-g00ecf From b3e625f6c14dc3354141a941f583adda1a9a939b Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sun, 27 Dec 2009 20:11:52 +0100 Subject: Make player-cast ioods restricted to the LOS radius. This is a discrepancy from the monster version, but since there's much fun to be had if we allow long-lived orbs, we'll explain that by a scribal error in most copies of spellbooks or something like that. --- crawl-ref/source/mon-project.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index d812be7982..d1d3ba4f3b 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -206,6 +206,13 @@ bool iood_act(monsters &mon, bool no_trail) return (true); } + if (mon.props["iood_kc"].get_byte() == KC_YOU + && (you.pos() - pos).rdist() >= LOS_RADIUS) + { // not actual vision, because of the smoke trail + _iood_dissipate(mon); + return (true); + } + if (pos == mon.pos()) return (false); -- cgit v1.2.3-54-g00ecf From 0bb2d8e6c92b777beb7126149ba2fadc200b461d Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sun, 27 Dec 2009 20:32:21 +0100 Subject: Don't make monsters seek projectiles. That's, uhm, unhealthy. --- crawl-ref/source/mon-behv.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/mon-behv.cc b/crawl-ref/source/mon-behv.cc index 98a1f3e853..5120688038 100644 --- a/crawl-ref/source/mon-behv.cc +++ b/crawl-ref/source/mon-behv.cc @@ -628,6 +628,7 @@ static bool _mons_check_foe(monsters *mon, const coord_def& p, { if (foe != mon && mon->can_see(foe) + && !mons_is_projectile(foe->type) && (friendly || !is_sanctuary(p)) && (foe->friendly() != friendly || (neutral && !foe->neutral()))) -- cgit v1.2.3-54-g00ecf From 8d1ebe62cbe392bdafb4c56d9ea250ca0f214678 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sun, 27 Dec 2009 20:34:08 +0100 Subject: Set the visible name to just "Orb of Destruction", "IOOD" is too long. --- crawl-ref/source/dat/database/monspell.txt | 2 +- crawl-ref/source/spl-data.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/dat/database/monspell.txt b/crawl-ref/source/dat/database/monspell.txt index d2dc14d325..0e3660d2db 100644 --- a/crawl-ref/source/dat/database/monspell.txt +++ b/crawl-ref/source/dat/database/monspell.txt @@ -117,7 +117,7 @@ unseen Symbol of Torment cast @The_something@ calls on the powers of Hell! %%%% -Iskenderun's Orb of Destruction cast +Orb of Destruction cast @The_monster@ conjures a glowing orb. diff --git a/crawl-ref/source/spl-data.h b/crawl-ref/source/spl-data.h index 215d28a2b8..d1f567d942 100644 --- a/crawl-ref/source/spl-data.h +++ b/crawl-ref/source/spl-data.h @@ -2642,7 +2642,7 @@ }, { - SPELL_IOOD, "Iskenderun's Orb of Destruction", + SPELL_IOOD, "Orb of Destruction", SPTYP_CONJURATION, SPFLAG_DIR_OR_TARGET | SPFLAG_NOT_SELF, 7, -- cgit v1.2.3-54-g00ecf From c2c12235d7a4f78e6725e55691a1c9e808d0d81a Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sun, 27 Dec 2009 20:57:03 +0100 Subject: Spell description for [i]ood. --- crawl-ref/source/dat/descript/spells.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crawl-ref/source/dat/descript/spells.txt b/crawl-ref/source/dat/descript/spells.txt index c79c9e1424..fb0256a781 100644 --- a/crawl-ref/source/dat/descript/spells.txt +++ b/crawl-ref/source/dat/descript/spells.txt @@ -378,6 +378,12 @@ Olgreb's Toxic Radiance This spell bathes the caster's surroundings in poisonous green light. %%%% +Orb of Destruction + +This spell conjures an orb made of pure destructive magic. Compared to most other projectiles, these orbs travel at a relatively slow pace. The orbs home onto their targets, yet because of their huge inertia, especially agile opponents may be able to outmaneuver them. + +It is said that most copies of this spell suffer from a scribal error that makes the orbs unstable beyond a short range. Certain individuals may have access to spellbooks without this flaw, so be ware! +%%%% Ozocubu's Armour This spell envelops the caster's body in a protective layer of ice, the power of which depends on his or her skill with ice magic. The caster and the caster's equipment are protected from the cold, but the spell will not function for casters already wearing heavy armour. The effects of this spell are boosted if the caster is in ice form. -- cgit v1.2.3-54-g00ecf From 0d5366e8b621e907dd4fbf7f4dd9f4ddd8376ffa Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sun, 27 Dec 2009 21:00:45 +0100 Subject: Add Orb of Destruction to allowed spells for pan lords and player ghosts. --- crawl-ref/source/ghost.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/ghost.cc b/crawl-ref/source/ghost.cc index e20e7e2317..69014f76d6 100644 --- a/crawl-ref/source/ghost.cc +++ b/crawl-ref/source/ghost.cc @@ -39,7 +39,6 @@ std::vector ghosts; // Order for looking for conjurations for the 1st & 2nd spell slots, // when finding spells to be remembered by a player's ghost. static spell_type search_order_conj[] = { -// 0 SPELL_LEHUDIBS_CRYSTAL_SPEAR, SPELL_FIRE_STORM, SPELL_ICE_STORM, @@ -50,8 +49,8 @@ static spell_type search_order_conj[] = { SPELL_LIGHTNING_BOLT, SPELL_AIRSTRIKE, SPELL_STICKY_FLAME, -// 10 SPELL_ISKENDERUNS_MYSTIC_BLAST, + SPELL_IOOD, SPELL_BOLT_OF_MAGMA, SPELL_THROW_ICICLE, SPELL_BOLT_OF_FIRE, @@ -61,7 +60,6 @@ static spell_type search_order_conj[] = { SPELL_VENOM_BOLT, SPELL_IRON_SHOT, SPELL_STONE_ARROW, -// 20 SPELL_THROW_FLAME, SPELL_THROW_FROST, SPELL_PAIN, @@ -285,6 +283,8 @@ void ghost_demon::init_random_demon() spells[1] = SPELL_ISKENDERUNS_MYSTIC_BLAST; if (one_chance_in(25)) spells[1] = SPELL_HELLFIRE; + if (one_chance_in(25)) + spells[1] = SPELL_IOOD; if (one_chance_in(25)) spells[2] = SPELL_SMITING; -- cgit v1.2.3-54-g00ecf From 1d0cbf5f8be4dcb3d78167d3a1f29691779298f8 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sun, 27 Dec 2009 23:36:38 +0100 Subject: A (sucky) pair of tiles for Orb of Destruction. --- crawl-ref/source/rltiles/dc-mon.txt | 1 + crawl-ref/source/rltiles/dc-mon/orb_of_destruction.png | Bin 0 -> 1012 bytes crawl-ref/source/rltiles/dc-spells.txt | 1 + .../rltiles/spells/conjuration/orb_of_destruction.png | Bin 0 -> 2481 bytes crawl-ref/source/tilepick.cc | 3 +++ 5 files changed, 5 insertions(+) create mode 100644 crawl-ref/source/rltiles/dc-mon/orb_of_destruction.png create mode 100644 crawl-ref/source/rltiles/spells/conjuration/orb_of_destruction.png diff --git a/crawl-ref/source/rltiles/dc-mon.txt b/crawl-ref/source/rltiles/dc-mon.txt index 3a48f1307d..49e246efe8 100644 --- a/crawl-ref/source/rltiles/dc-mon.txt +++ b/crawl-ref/source/rltiles/dc-mon.txt @@ -160,6 +160,7 @@ death_cob MONS_DEATH_COB /*'%'*/ ball_lightning MONS_BALL_LIGHTNING /*'*'*/ %rim 0 orb_of_fire MONS_ORB_OF_FIRE /*'*'*/ +orb_of_destruction MONS_ORB_OF_DESTRUCTION /*'*'*/ %rim 1 ### Demonic monsters diff --git a/crawl-ref/source/rltiles/dc-mon/orb_of_destruction.png b/crawl-ref/source/rltiles/dc-mon/orb_of_destruction.png new file mode 100644 index 0000000000..b328f0a7ca Binary files /dev/null and b/crawl-ref/source/rltiles/dc-mon/orb_of_destruction.png differ diff --git a/crawl-ref/source/rltiles/dc-spells.txt b/crawl-ref/source/rltiles/dc-spells.txt index 8dbf264f4e..6c88296a71 100644 --- a/crawl-ref/source/rltiles/dc-spells.txt +++ b/crawl-ref/source/rltiles/dc-spells.txt @@ -30,6 +30,7 @@ swiftness SWIFTNESS %sdir spells/conjuration iskenderuns_mystic_blast ISKENDERUNS_MYSTIC_BLAST magic_dart MAGIC_DART +orb_of_destruction IOOD %sdir spells/divination detect_creatures DETECT_CREATURES diff --git a/crawl-ref/source/rltiles/spells/conjuration/orb_of_destruction.png b/crawl-ref/source/rltiles/spells/conjuration/orb_of_destruction.png new file mode 100644 index 0000000000..574d0194ad Binary files /dev/null and b/crawl-ref/source/rltiles/spells/conjuration/orb_of_destruction.png differ diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index 34cbf7eb7f..4a0a8b2fb1 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -910,6 +910,8 @@ int tileidx_monster_base(const monsters *mon, bool detected) return TILEP_MONS_BALL_LIGHTNING; case MONS_ORB_OF_FIRE: return TILEP_MONS_ORB_OF_FIRE; + case MONS_ORB_OF_DESTRUCTION: + return TILEP_MONS_ORB_OF_DESTRUCTION; // other symbols case MONS_VAPOUR: @@ -3044,6 +3046,7 @@ int tileidx_spell(spell_type spell) // pure Conjuration case SPELL_MAGIC_DART: return TILEG_MAGIC_DART; case SPELL_ISKENDERUNS_MYSTIC_BLAST: return TILEG_ISKENDERUNS_MYSTIC_BLAST; + case SPELL_IOOD: return TILEG_IOOD; // Divination (soon to be obsolete, or moved to abilities) case SPELL_DETECT_SECRET_DOORS: return TILEG_DETECT_SECRET_DOORS; -- cgit v1.2.3-54-g00ecf From fdfbfdeb226cb33da8198cb3da6b6f39d7118dfc Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Wed, 30 Dec 2009 14:42:38 +0100 Subject: A new cloud type: magical condensation trails, used by IOOD. --- crawl-ref/source/cloud.cc | 7 +++++++ crawl-ref/source/enum.h | 1 + crawl-ref/source/mon-project.cc | 2 +- crawl-ref/source/tutorial.cc | 1 + 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/cloud.cc b/crawl-ref/source/cloud.cc index 58eb185c97..823164846d 100644 --- a/crawl-ref/source/cloud.cc +++ b/crawl-ref/source/cloud.cc @@ -886,6 +886,7 @@ bool is_harmless_cloud(cloud_type type) case CLOUD_TLOC_ENERGY: case CLOUD_MIST: case CLOUD_RAIN: + case CLOUD_MAGIC_TRAIL: case CLOUD_DEBUGGING: return (true); default: @@ -960,6 +961,8 @@ std::string cloud_name(cloud_type type) return "rain"; case CLOUD_MUTAGENIC: return "mutagenic fog"; + case CLOUD_MAGIC_TRAIL: + return "magical condensation"; default: return "buggy goodness"; } @@ -1096,6 +1099,10 @@ int get_cloud_colour(int cloudno) which_colour = ETC_MUTAGENIC; break; + case CLOUD_MAGIC_TRAIL: + which_colour = ETC_MAGIC; + break; + default: which_colour = LIGHTGREY; break; diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index 5ea569e163..a3eca5e4b2 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -442,6 +442,7 @@ enum cloud_type CLOUD_CHAOS, CLOUD_RAIN, CLOUD_MUTAGENIC, + CLOUD_MAGIC_TRAIL, CLOUD_RANDOM = 98, CLOUD_DEBUGGING = 99 // 99: used once as 'nonexistent cloud' {dlb} }; diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index d1d3ba4f3b..0af08ef38d 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -242,7 +242,7 @@ bool iood_act(monsters &mon, bool no_trail) if (!no_trail) { - place_cloud(CLOUD_GREY_SMOKE, mon.pos(), + place_cloud(CLOUD_MAGIC_TRAIL, mon.pos(), 2 + random2(3), mon.kill_alignment(), KILL_MON_MISSILE); } diff --git a/crawl-ref/source/tutorial.cc b/crawl-ref/source/tutorial.cc index e0e7d53b72..1b173c694b 100644 --- a/crawl-ref/source/tutorial.cc +++ b/crawl-ref/source/tutorial.cc @@ -4462,6 +4462,7 @@ static void _tutorial_describe_cloud(int x, int y) case CLOUD_TLOC_ENERGY: case CLOUD_PURPLE_SMOKE: case CLOUD_MIST: + case CLOUD_MAGIC_TRAIL: ostr << "harmless. "; break; -- cgit v1.2.3-54-g00ecf From 8d8a727b80167a76d8282614fff1610fd9625a61 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Thu, 31 Dec 2009 14:08:54 +0100 Subject: IOOD vs shields: blocks (boo!) and reflection (yay!) --- crawl-ref/source/beam.cc | 10 ++---- crawl-ref/source/itemprop.cc | 6 ++++ crawl-ref/source/itemprop.h | 1 + crawl-ref/source/mon-project.cc | 72 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index 41eddbe46b..e991e44b51 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -3720,12 +3720,6 @@ bool bolt::is_reflectable(const item_def *it) const return (it && is_shield(*it) && shield_reflects(*it)); } -static void _ident_reflector(item_def *item) -{ - if (!is_artefact(*item)) - set_ident_flags(*item, ISFLAG_KNOW_TYPE); -} - // Reflect a beam back the direction it came. This is used // by shields of reflection. void bolt::reflect() @@ -3852,7 +3846,7 @@ bool bolt::misses_player() mprf( "Your %s reflects the %s!", you.shield()->name(DESC_PLAIN).c_str(), name.c_str() ); - _ident_reflector(you.shield()); + ident_reflector(you.shield()); reflect(); } else @@ -4818,7 +4812,7 @@ bool bolt::attempt_block(monsters* mon) name.c_str(), mon->pronoun(PRONOUN_NOCAP_POSSESSIVE).c_str(), shield->name(DESC_PLAIN).c_str()); - _ident_reflector(shield); + ident_reflector(shield); } else if (you.see_cell(pos())) mprf("The %s bounces off of thin air!", name.c_str()); diff --git a/crawl-ref/source/itemprop.cc b/crawl-ref/source/itemprop.cc index bf47f3ab96..88b579114d 100644 --- a/crawl-ref/source/itemprop.cc +++ b/crawl-ref/source/itemprop.cc @@ -2462,6 +2462,12 @@ bool shield_reflects(const item_def &shield) return (get_armour_ego_type(shield) == SPARM_REFLECTION); } +void ident_reflector(item_def *item) +{ + if (!is_artefact(*item)) + set_ident_flags(*item, ISFLAG_KNOW_TYPE); +} + std::string item_base_name(const item_def &item) { switch (item.base_type) diff --git a/crawl-ref/source/itemprop.h b/crawl-ref/source/itemprop.h index 5604d352f5..d1231bc9f5 100644 --- a/crawl-ref/source/itemprop.h +++ b/crawl-ref/source/itemprop.h @@ -84,6 +84,7 @@ bool is_shield(const item_def &item); bool is_shield_incompatible(const item_def &weapon, const item_def *shield = NULL); bool shield_reflects(const item_def &shield); +void ident_reflector(item_def *item); // Only works for armour/weapons/missiles // weapon functions: diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index 0af08ef38d..86ebc0a983 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -19,6 +19,7 @@ #include "directn.h" #include "coord.h" #include "env.h" +#include "itemprop.h" #include "mgen_data.h" #include "mon-place.h" #include "mon-stuff.h" @@ -88,6 +89,19 @@ void _iood_dissipate(monsters &mon) monster_die(&mon, KILL_DISMISSED, NON_MONSTER); } +// Alas, too much differs to reuse beam shield blocks :( +bool _iood_shielded(monsters &mon, actor &victim) +{ + if (!victim.shield() || victim.incapacitated()) + return (false); + + const int to_hit = 15 + mon.props["iood_pow"].get_short()/12; + const int con_block = random2(to_hit + victim.shield_block_penalty()); + const int pro_block = victim.shield_bonus(); + dprf("iood shield: pro %d, con %d", pro_block, con_block); + return (pro_block >= con_block); +} + bool _iood_hit(monsters &mon, const coord_def &pos, bool big_boom = false) { bolt beam; @@ -193,6 +207,8 @@ bool iood_act(monsters &mon, bool no_trail) mon.props["iood_vy"] = vy; } +reflected: + x += vx; y += vy; @@ -236,6 +252,62 @@ bool iood_act(monsters &mon, bool no_trail) return (true); } + if (victim && _iood_shielded(mon, *victim)) + { + item_def *shield = victim->shield(); + if (!shield_reflects(*shield)) + { + if (victim->atype() == ACT_PLAYER) + { + mprf("You block %s.", mon.name(DESC_NOCAP_THE, true).c_str()); + } + else + { + simple_monster_message((monsters*)victim, (" blocks the " + + mon.name(DESC_NOCAP_THE, true) + ".").c_str()); + } + victim->shield_block_succeeded(&mon); + _iood_dissipate(mon); + return (true); + } + + if (victim->atype() == ACT_PLAYER) + { + mprf("Your %s reflects %s!", + shield->name(DESC_PLAIN).c_str(), + mon.name(DESC_NOCAP_THE, true).c_str()); + ident_reflector(shield); + } + else if (you.see_cell(pos)) + { + if (victim->observable()) + { + mprf("%s reflects %s with %s %s!", + victim->name(DESC_CAP_THE, true).c_str(), + mon.name(DESC_NOCAP_THE, true).c_str(), + mon.pronoun(PRONOUN_NOCAP_POSSESSIVE).c_str(), + shield->name(DESC_PLAIN).c_str()); + ident_reflector(shield); + } + else + { + mprf("%s bounces off thin air!", + mon.name(DESC_CAP_THE, true).c_str()); + } + } + victim->shield_block_succeeded(&mon); + + mon.props["iood_vx"] = vx = -vx; + mon.props["iood_vy"] = vy = -vy; + + // Need to get out of the victim's square. + + // If you're next to the caster and both of you wear shields of + // reflection, this can lead to a brief game of ping-pong, but + // rapidly increasing shield penalties will make it short. + goto reflected; + } + if (_iood_hit(mon, pos)) return (true); } -- cgit v1.2.3-54-g00ecf From d9455c8463eda0347a0fa230190454c56b193ebc Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Thu, 31 Dec 2009 14:19:44 +0100 Subject: Don't give exp for kills by neutrals. --- crawl-ref/source/mon-project.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index 86ebc0a983..b2641fbafa 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -36,7 +36,7 @@ bool cast_iood(actor *caster, int pow, bolt *beam) int mind = mons_place(mgen_data(MONS_ORB_OF_DESTRUCTION, (caster->atype() == ACT_PLAYER) ? BEH_FRIENDLY : - ((monsters*)caster)->wont_attack() ? BEH_FRIENDLY : BEH_HOSTILE, + ((monsters*)caster)->friendly() ? BEH_FRIENDLY : BEH_HOSTILE, caster, 0, SPELL_IOOD, @@ -57,7 +57,7 @@ bool cast_iood(actor *caster, int pow, bolt *beam) mon.props["iood_vx"] = (float)(beam->target.x - pos.x); mon.props["iood_vy"] = (float)(beam->target.y - pos.y); mon.props["iood_kc"].get_byte() = (caster->atype() == ACT_PLAYER) ? KC_YOU : - ((monsters*)caster)->wont_attack() ? KC_FRIENDLY : KC_OTHER; + ((monsters*)caster)->friendly() ? KC_FRIENDLY : KC_OTHER; mon.props["iood_pow"].get_short() = pow; mon.flags &= ~MF_JUST_SUMMONED; -- cgit v1.2.3-54-g00ecf From 9939a9514e001f19dc384d8ae8b27940327afbe8 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Thu, 31 Dec 2009 14:45:31 +0100 Subject: Apply a stepdown on power to make damage more constant. --- crawl-ref/source/mon-project.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index b2641fbafa..b5806b7089 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -116,7 +116,8 @@ bool _iood_hit(monsters &mon, const coord_def &pos, bool big_boom = false) beam.source = pos; beam.target = pos; beam.hit = AUTOMATIC_HIT; - beam.damage = dice_def(6, mon.props["iood_pow"].get_short()/4); + const int pow = mon.props["iood_pow"].get_short(); + beam.damage = dice_def(8, stepdown_value(pow, 30, 30, 200, -1) / 4); beam.ex_size = 1; monster_die(&mon, KILL_DISMISSED, NON_MONSTER); -- cgit v1.2.3-54-g00ecf