summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Borowski <kilobyte@angband.pl>2009-12-19 22:51:57 +0100
committerAdam Borowski <kilobyte@angband.pl>2009-12-20 17:29:36 +0100
commit0cebeb433d68aea197f5ee1d2c38809b71c2e3dd (patch)
tree67cea0b5ab60075666e8ca110c9aa7035bfa0d79
parent7e4b512c4cf3b6269ddb3748760c8cf050b60b39 (diff)
downloadcrawl-ref-0cebeb433d68aea197f5ee1d2c38809b71c2e3dd.tar.gz
crawl-ref-0cebeb433d68aea197f5ee1d2c38809b71c2e3dd.zip
Iskenderun's Orb of Destruction
-rw-r--r--crawl-ref/source/beam.cc18
-rw-r--r--crawl-ref/source/enum.h6
-rw-r--r--crawl-ref/source/fight.cc3
-rw-r--r--crawl-ref/source/main.cc2
-rw-r--r--crawl-ref/source/makefile.obj1
-rw-r--r--crawl-ref/source/mgen_data.h2
-rw-r--r--crawl-ref/source/mon-act.cc16
-rw-r--r--crawl-ref/source/mon-data.h13
-rw-r--r--crawl-ref/source/mon-project.cc172
-rw-r--r--crawl-ref/source/mon-project.h17
-rw-r--r--crawl-ref/source/mon-util.cc3
-rw-r--r--crawl-ref/source/spl-book.cc2
-rw-r--r--crawl-ref/source/spl-cast.cc8
-rw-r--r--crawl-ref/source/spl-data.h13
14 files changed, 268 insertions, 8 deletions
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<AUTOMATIC_HIT>,
+ 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 <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <cmath>
+
+#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
@@ -2590,6 +2590,19 @@
},
{
+ 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,
SPFLAG_TESTING,