From 380661f014abdc14c12dc5a9bf10a73be822821c Mon Sep 17 00:00:00 2001 From: zelgadis Date: Wed, 4 Jun 2008 23:38:05 +0000 Subject: Added trapdoor spider (not yet randomly generated). If a trapdoor spider can't see any enemies and is on a floor square it will "submurge" into the floor and only come out if an enemy moves right next to it or if something attacks it from a distance. Most of this is done with the new monster behavour BEH_LURK. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5477 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/enum.h | 4 ++- crawl-ref/source/mon-data.h | 11 ++++++ crawl-ref/source/mon-util.cc | 61 +++++++++++++++++++++++++++++--- crawl-ref/source/monplace.cc | 3 ++ crawl-ref/source/monstuff.cc | 84 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 158 insertions(+), 5 deletions(-) (limited to 'crawl-ref/source') 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 @@ -1252,6 +1252,17 @@ HT_LAND, 15, DEFAULT_ENERGY, MONUSE_NOTHING, SIZE_TINY }, +{ + 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, 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)) { -- cgit v1.2.3-54-g00ecf