summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/enum.h4
-rw-r--r--crawl-ref/source/mon-data.h11
-rw-r--r--crawl-ref/source/mon-util.cc61
-rw-r--r--crawl-ref/source/monplace.cc3
-rw-r--r--crawl-ref/source/monstuff.cc84
5 files changed, 158 insertions, 5 deletions
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index a267d894af..1a906c9303 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -1794,7 +1794,7 @@ enum monster_type // (int) menv[].type
MONS_BALL_LIGHTNING, // replacing the dorgi -- bwr 380
MONS_ORB_OF_FIRE, // Swords renamed to fit -- bwr
MONS_QUOKKA, // Quokka are a type of wallaby, returned -- bwr 382
- // 383
+ MONS_TRAPDOOR_SPIDER,
// 384
MONS_EYE_OF_DEVASTATION = 385, // 385
MONS_MOTH_OF_WRATH,
@@ -1867,6 +1867,8 @@ enum beh_type
BEH_CORNERED,
BEH_PANIC, // like flee but without running away
BEH_INVESTIGATE, // investigating an ME_DISTURB
+ BEH_LURK, // stay still until discovered or
+ // enemy closeby
NUM_BEHAVIOURS, // max # of legal states
BEH_CHARMED, // hostile-but-charmed; create only
BEH_FRIENDLY, // used during creation only
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index c0d3419359..5d4201287f 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -1253,6 +1253,17 @@
},
{
+ MONS_TRAPDOOR_SPIDER, 's', BROWN, "trapdoor spider",
+ M_NO_FLAGS,
+ MR_VUL_POISON,
+ 800, 10, MONS_WOLF_SPIDER, MONS_WOLF_SPIDER, MH_NATURAL, -3,
+ { {AT_BITE, AF_POISON_MEDIUM, 20}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
+ { 8, 3, 5, 0 },
+ 3, 10, MST_NO_SPELLS, CE_POISONOUS, Z_BIG, S_HISS, I_INSECT,
+ HT_LAND, 15, DEFAULT_ENERGY, MONUSE_NOTHING, SIZE_TINY
+},
+
+{
MONS_REDBACK, 's', RED, "redback",
M_NO_FLAGS,
MR_VUL_POISON,
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 6e13d29153..31c70f4404 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -4762,6 +4762,15 @@ void monsters::add_enchantment_effect(const mon_enchant &ench, bool quiet)
case ENCH_BERSERK:
// Inflate hp.
scale_hp(3, 2);
+
+ if (has_ench(ENCH_SUBMERGED))
+ del_ench(ENCH_SUBMERGED);
+
+ if (behaviour == BEH_LURK)
+ {
+ behaviour = BEH_WANDER;
+ behaviour_event(this, ME_EVAL);
+ }
break;
case ENCH_HASTE:
@@ -4781,10 +4790,30 @@ void monsters::add_enchantment_effect(const mon_enchant &ench, bool quiet)
break;
case ENCH_SUBMERGED:
- if (type == MONS_AIR_ELEMENTAL && mons_near(this) && !quiet)
+ // XXX: What if the monster was invisible before submerging?
+ if (mons_near(this) && !quiet)
{
- mprf("%s merges itself into the air.",
- name(DESC_CAP_A, true).c_str() );
+ if (type == MONS_AIR_ELEMENTAL)
+ {
+ mprf("%s merges itself into the air.",
+ name(DESC_CAP_A, true).c_str() );
+ }
+ else if (type == MONS_TRAPDOOR_SPIDER)
+ {
+ mprf("%s hides itself under the floor.",
+ name(DESC_CAP_A, true).c_str() );
+ }
+ }
+ break;
+
+ case ENCH_CONFUSION:
+ if (type == MONS_TRAPDOOR_SPIDER && has_ench(ENCH_SUBMERGED))
+ del_ench(ENCH_SUBMERGED);
+
+ if (behaviour == BEH_LURK)
+ {
+ behaviour = BEH_WANDER;
+ behaviour_event(this, ME_EVAL);
}
break;
@@ -4973,6 +5002,8 @@ void monsters::remove_enchantment_effect(const mon_enchant &me, bool quiet)
if (type == MONS_AIR_ELEMENTAL)
seen_context = "thin air";
+ else if (type == MONS_TRAPDOOR_SPIDER)
+ seen_context = "leaps out";
else if (monster_habitable_grid(this, DNGN_FLOOR))
seen_context = "bursts forth";
else
@@ -4985,6 +5016,11 @@ void monsters::remove_enchantment_effect(const mon_enchant &me, bool quiet)
mprf("%s forms itself from the air!",
name(DESC_CAP_A, true).c_str() );
}
+ else if (type == MONS_TRAPDOOR_SPIDER)
+ {
+ mprf("%s leaps out from its hiding place under the floor!",
+ name(DESC_CAP_A, true).c_str() );
+ }
}
}
else if (mons_near(this) && monster_habitable_grid(this, DNGN_FLOOR))
@@ -4993,6 +5029,12 @@ void monsters::remove_enchantment_effect(const mon_enchant &me, bool quiet)
interrupt_activity( AI_FORCE_INTERRUPT );
}
+ if (behaviour == BEH_WANDER)
+ {
+ behaviour = BEH_SEEK;
+ behaviour_event(this, ME_EVAL);
+ }
+
break;
default:
@@ -5376,6 +5418,13 @@ void monsters::apply_enchantment(const mon_enchant &me)
// and are more likely to surface. -- bwr
if (!monster_can_submerge(this, grid))
del_ench(ENCH_SUBMERGED); // forced to surface
+ else if (type == MONS_TRAPDOOR_SPIDER)
+ {
+ // This should probably never happen.
+ if (behaviour != BEH_LURK)
+ del_ench(ENCH_SUBMERGED);
+ break;
+ }
else if (hit_points <= max_hit_points / 2)
break;
else if (((type == MONS_ELECTRICAL_EEL || type == MONS_LAVA_SNAKE)
@@ -5801,9 +5850,13 @@ void monsters::apply_location_effects()
mons_check_pool(this);
if (alive() && has_ench(ENCH_SUBMERGED)
- && !monster_can_submerge(this, grd[x][y]))
+ && (!monster_can_submerge(this, grd[x][y])
+ || type == MONS_TRAPDOOR_SPIDER))
{
del_ench(ENCH_SUBMERGED);
+
+ if (type == MONS_TRAPDOOR_SPIDER)
+ behaviour_event(this, ME_EVAL);
}
}
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index 5ea9a3b5d7..9dfeb99694 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -158,6 +158,9 @@ bool monster_habitable_grid(int monster_class,
// Returns true if the monster can submerge in the given grid.
bool monster_can_submerge(const monsters *mons, dungeon_feature_type grid)
{
+ if (mons->type == MONS_TRAPDOOR_SPIDER && grid == DNGN_FLOOR)
+ return true;
+
// Zombies of watery critters can not submerge.
switch (mons_habitat(mons))
{
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index f73071735c..48ffe155c7 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -1465,6 +1465,10 @@ static bool _valid_morph( monsters *monster, int new_mclass )
|| new_mclass == MONS_PLAYER_GHOST
|| new_mclass == MONS_PANDEMONIUM_DEMON
+ // Monsters still under development
+ || new_mclass == MONS_ROCK_WORM
+ || new_mclass == MONS_TRAPDOOR_SPIDER
+
// Other poly-unsuitable things.
|| new_mclass == MONS_ROYAL_JELLY
|| new_mclass == MONS_ORB_GUARDIAN
@@ -2016,6 +2020,8 @@ static bool _wounded_damaged(int monster_type)
void behaviour_event( monsters *mon, int event, int src,
int src_x, int src_y )
{
+ beh_type old_behaviour = mon->behaviour;
+
bool isSmart = (mons_intel(mon->type) > I_ANIMAL);
bool wontAttack = mons_wont_attack(mon);
bool sourceWontAttack = false;
@@ -2160,6 +2166,25 @@ void behaviour_event( monsters *mon, int event, int src,
// Do any resultant foe or state changes.
_handle_behaviour( mon );
+
+ if (old_behaviour == BEH_LURK && mon->behaviour != BEH_LURK)
+ {
+ switch(event)
+ {
+ case ME_EVAL:
+ case ME_DISTURB:
+ case ME_ALERT:
+ // Lurking monsters won't stop lurking just because they
+ // noticed something.
+ mon->behaviour = BEH_LURK;
+ break;
+
+ default:
+ if (mon->has_ench(ENCH_SUBMERGED))
+ mon->del_ench(ENCH_SUBMERGED);
+ break;
+ }
+ }
}
static bool _choose_random_patrol_target_grid(monsters *mon)
@@ -2476,6 +2501,7 @@ static void _handle_behaviour(monsters *mon)
new_foe = MHITNOT;
break;
+ case BEH_LURK:
case BEH_SEEK:
// No foe? Then wander or seek the player.
if (mon->foe == MHITNOT)
@@ -3121,6 +3147,7 @@ static void _handle_nearby_ability(monsters *monster)
if (monster_can_submerge(monster, grd[monster->x][monster->y])
&& !player_beheld_by(monster) // No submerging if player entranced.
+ && monster->behaviour != BEH_LURK // Handled elsewhere
&& (one_chance_in(5)
|| grid_distance( monster->x, monster->y,
you.x_pos, you.y_pos ) > 1
@@ -5176,6 +5203,38 @@ static void _handle_monster_move(int i, monsters *monster)
}
}
+ if (monster->behaviour == BEH_LURK)
+ {
+ // Lurking monsters only stop lurking if their target is right
+ // next tp them, otherwise they just sit there.
+ if (monster->foe != MHITNOT
+ && abs(monster->target_x - monster->x) <= 1
+ && abs(monster->target_y - monster->y) <= 1)
+ {
+ if (monster->has_ench(ENCH_SUBMERGED))
+ {
+ // Don't unsubmerge if the player is right on top,
+ // if the monster is too damaged or if the monster
+ // is afraid.
+ if (monster->pos() == you.pos()
+ || monster->hit_points <= monster->max_hit_points / 2
+ || monster->has_ench(ENCH_FEAR))
+ {
+ monster->speed_increment -= non_move_energy;
+ continue;
+ }
+
+ monster->del_ench(ENCH_SUBMERGED);
+ }
+ monster->behaviour = BEH_SEEK;
+ }
+ else
+ {
+ monster->speed_increment -= non_move_energy;
+ continue;
+ }
+ }
+
if (mons_is_caught(monster))
{
// Struggling against the net takes time.
@@ -6312,6 +6371,31 @@ static bool _monster_move(monsters *monster)
const habitat_type habitat = mons_habitat(monster);
bool deep_water_available = false;
+ if (monster->type == MONS_TRAPDOOR_SPIDER)
+ {
+ if(monster->has_ench(ENCH_SUBMERGED))
+ return false;
+
+ // Trapdoor spiders hide if they can't see their target.
+ bool can_see;
+
+ if (monster->foe == MHITNOT)
+ can_see = false;
+ else if (monster->foe == MHITYOU)
+ can_see = monster->can_see(&you);
+ else
+ can_see = monster->can_see(&menv[monster->foe]);
+
+ if (monster_can_submerge(monster, grd[monster->x][monster->y])
+ && !can_see && !mons_is_confused(monster)
+ && !monster->has_ench(ENCH_BERSERK))
+ {
+ monster->add_ench(ENCH_SUBMERGED);
+ monster->behaviour = BEH_LURK;
+ return false;
+ }
+ }
+
// Berserking monsters make a lot of racket.
if (monster->has_ench(ENCH_BERSERK))
{