summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/monstuff.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/monstuff.cc')
-rw-r--r--crawl-ref/source/monstuff.cc312
1 files changed, 191 insertions, 121 deletions
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 87b238f9e5..f722a5a23a 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -1123,6 +1123,7 @@ bool monster_polymorph( monsters *monster, monster_type targetc,
// the actual polymorphing:
const int old_hp = monster->hit_points;
const int old_hp_max = monster->max_hit_points;
+ const bool old_mon_caught = mons_is_caught(monster);
/* deal with mons_sec */
monster->type = targetc;
@@ -1166,6 +1167,40 @@ bool monster_polymorph( monsters *monster, monster_type targetc,
if (player_monster_visible(monster) && mons_near(monster))
seen_monster(monster);
+ if (old_mon_caught)
+ {
+ if (monster->body_size(PSIZE_BODY) >= SIZE_GIANT)
+ {
+ int net, next;
+ for (net = igrd[monster->x][monster->y]; net != NON_ITEM; net = next)
+ {
+ next = mitm[net].link;
+
+ if (mitm[net].base_type == OBJ_MISSILES
+ && mitm[net].sub_type == MI_THROWING_NET)
+ {
+ break;
+ }
+ }
+ dec_mitm_item_quantity( net, 1 );
+
+ if (see_grid(monster->x, monster->y))
+ {
+ if (player_monster_visible(monster))
+ {
+ mprf("The net rips apart, and %s comes free!",
+ monster->name(DESC_NOCAP_THE).c_str());
+ }
+ else
+ {
+ mpr("All of a sudden the net rips apart!");
+ }
+ }
+ }
+ else
+ monster->add_ench(ENCH_CAUGHT);
+ }
+
return (player_messaged);
} // end monster_polymorph()
@@ -1190,6 +1225,9 @@ bool monster_blink(monsters *monster)
monster->check_redraw(oldplace);
monster->apply_location_effects();
+
+ if (monster->has_ench(ENCH_CAUGHT))
+ monster->del_ench(ENCH_CAUGHT, true);
return (true);
} // end monster_blink()
@@ -2419,7 +2457,7 @@ static bool handle_special_ability(monsters *monster, bolt & beem)
case MONS_INSUBSTANTIAL_WISP:
case MONS_BLINK_FROG:
case MONS_KILLER_KLOWN:
- if (one_chance_in(7))
+ if (one_chance_in(7) || mons_is_caught(monster) && one_chance_in(3))
{
simple_monster_message(monster, " blinks.");
monster_blink(monster);
@@ -2686,7 +2724,7 @@ static bool handle_scroll(monsters *monster)
case SCR_TELEPORTATION:
if (!monster->has_ench(ENCH_TP))
{
- if (monster->behaviour == BEH_FLEE)
+ if (monster->behaviour == BEH_FLEE || monster->has_ench(ENCH_CAUGHT))
{
simple_monster_message(monster, " reads a scroll.");
monster_teleport(monster, false);
@@ -2696,7 +2734,7 @@ static bool handle_scroll(monsters *monster)
break;
case SCR_BLINKING:
- if (monster->behaviour == BEH_FLEE)
+ if (monster->behaviour == BEH_FLEE || monster->has_ench(ENCH_CAUGHT))
{
if (mons_near(monster))
{
@@ -2839,7 +2877,8 @@ static bool handle_wand(monsters *monster, bolt &beem)
return (false);
case WAND_TELEPORTATION:
- if (monster->hit_points <= monster->max_hit_points / 2)
+ if (monster->hit_points <= monster->max_hit_points / 2
+ || mons_is_caught(monster))
{
if (!monster->has_ench(ENCH_TP)
&& !one_chance_in(20))
@@ -3214,6 +3253,23 @@ static bool handle_spell( monsters *monster, bolt & beem )
}
}
+ // monsters caught in a net try to get away
+ // this is only urgent if you are around
+ if (!finalAnswer && monsterNearby && mons_is_caught(monster)
+ && one_chance_in(3))
+ {
+ if (ms_quick_get_away( monster, hspell_pass[6]))
+ {
+ spell_cast = hspell_pass[6];
+ finalAnswer = true;
+ }
+ else if (ms_quick_get_away( monster, hspell_pass[5]))
+ {
+ spell_cast = hspell_pass[5];
+ finalAnswer = true;
+ }
+ }
+
// Promote the casting of useful spells for low-HP monsters.
if (!finalAnswer
&& monster->hit_points < monster->max_hit_points / 4
@@ -3686,7 +3742,7 @@ static void handle_monster_move(int i, monsters *monster)
continue;
handle_behaviour(monster);
-
+
// submerging monsters will hide from clouds
if (monster_can_submerge(monster->type, grd[monster->x][monster->y])
&& env.cgrid[monster->x][monster->y] != EMPTY_CLOUD)
@@ -3721,71 +3777,73 @@ static void handle_monster_move(int i, monsters *monster)
}
}
- // calculates mmov_x, mmov_y based on monster target.
- handle_movement(monster);
-
- brkk = false;
-
- if (mons_is_confused( monster )
- || (monster->type == MONS_AIR_ELEMENTAL
- && monster->has_ench(ENCH_SUBMERGED)))
+ if (!mons_is_caught(monster))
{
- std::vector<coord_def> moves;
-
- int pfound = 0;
- for (int yi = -1; yi <= 1; ++yi)
- {
- for (int xi = -1; xi <= 1; ++xi)
- {
- coord_def c = monster->pos() + coord_def(xi, yi);
- if (in_bounds(c) && !grid_is_solid(grd(c))
- && one_chance_in(++pfound))
- {
- mmov_x = xi;
- mmov_y = yi;
- }
- }
- }
-
- if (random2(2 + pfound) < 2)
- mmov_x = mmov_y = 0;
-
- // bounds check: don't let confused monsters try to run
- // off the map
- if (monster->x + mmov_x < 0
- || monster->x + mmov_x >= GXM)
- {
- mmov_x = 0;
- }
-
- if (monster->y + mmov_y < 0
- || monster->y + mmov_y >= GYM)
- {
- mmov_y = 0;
- }
-
- if (grid_is_solid(
- grd[ monster->x + mmov_x ][ monster->y + mmov_y ]))
- {
- mmov_x = mmov_y = 0;
- }
-
- if (mgrd[monster->x + mmov_x][monster->y + mmov_y] != NON_MONSTER
- && (mmov_x != 0 || mmov_y != 0))
- {
- monsters_fight(
- i,
- mgrd[monster->x + mmov_x][monster->y + mmov_y]);
+ // calculates mmov_x, mmov_y based on monster target.
+ handle_movement(monster);
+
+ brkk = false;
+
+ if (mons_is_confused( monster )
+ || (monster->type == MONS_AIR_ELEMENTAL
+ && monster->has_ench(ENCH_SUBMERGED)))
+ {
+ std::vector<coord_def> moves;
+
+ int pfound = 0;
+ for (int yi = -1; yi <= 1; ++yi)
+ {
+ for (int xi = -1; xi <= 1; ++xi)
+ {
+ coord_def c = monster->pos() + coord_def(xi, yi);
+ if (in_bounds(c) && !grid_is_solid(grd(c))
+ && one_chance_in(++pfound))
+ {
+ mmov_x = xi;
+ mmov_y = yi;
+ }
+ }
+ }
+
+ if (random2(2 + pfound) < 2)
+ mmov_x = mmov_y = 0;
+
+ // bounds check: don't let confused monsters try to run
+ // off the map
+ if (monster->x + mmov_x < 0
+ || monster->x + mmov_x >= GXM)
+ {
+ mmov_x = 0;
+ }
+
+ if (monster->y + mmov_y < 0
+ || monster->y + mmov_y >= GYM)
+ {
+ mmov_y = 0;
+ }
+
+ if (grid_is_solid(
+ grd[ monster->x + mmov_x ][ monster->y + mmov_y ]))
+ {
+ mmov_x = mmov_y = 0;
+ }
+
+ if (mgrd[monster->x + mmov_x][monster->y + mmov_y] != NON_MONSTER
+ && (mmov_x != 0 || mmov_y != 0))
+ {
+ monsters_fight(
+ i,
+ mgrd[monster->x + mmov_x][monster->y + mmov_y]);
- brkk = true;
- mmov_x = 0;
- mmov_y = 0;
- }
+ brkk = true;
+ mmov_x = 0;
+ mmov_y = 0;
+ }
+ }
+
+ if (brkk)
+ continue;
}
-
- if (brkk)
- continue;
-
handle_nearby_ability( monster );
beem.target_x = monster->target_x;
@@ -3832,78 +3890,80 @@ static void handle_monster_move(int i, monsters *monster)
continue;
}
- // see if we move into (and fight) an unfriendly monster
- int targmon = mgrd[monster->x + mmov_x][monster->y + mmov_y];
- if (targmon != NON_MONSTER
- && targmon != i
- && !mons_aligned(i, targmon))
+ if (!mons_is_caught(monster))
{
- // figure out if they fight
- if (monsters_fight(i, targmon))
+ // see if we move into (and fight) an unfriendly monster
+ int targmon = mgrd[monster->x + mmov_x][monster->y + mmov_y];
+ if (targmon != NON_MONSTER
+ && targmon != i
+ && !mons_aligned(i, targmon))
{
- if (testbits(monster->flags, MF_BATTY))
+ // figure out if they fight
+ if (monsters_fight(i, targmon))
{
- monster->behaviour = BEH_WANDER;
- monster->target_x = 10 + random2(GXM - 10);
- monster->target_y = 10 + random2(GYM - 10);
- // monster->speed_increment -= monster->speed;
- }
+ if (testbits(monster->flags, MF_BATTY))
+ {
+ monster->behaviour = BEH_WANDER;
+ monster->target_x = 10 + random2(GXM - 10);
+ monster->target_y = 10 + random2(GYM - 10);
+ // monster->speed_increment -= monster->speed;
+ }
- mmov_x = 0;
- mmov_y = 0;
- brkk = true;
+ mmov_x = 0;
+ mmov_y = 0;
+ brkk = true;
+ }
}
- }
-
- if (brkk)
- continue;
- if (monster->x + mmov_x == you.x_pos
- && monster->y + mmov_y == you.y_pos)
- {
- bool isFriendly = mons_friendly(monster);
- bool attacked = false;
+ if (brkk)
+ continue;
- if (!isFriendly)
+ if (monster->x + mmov_x == you.x_pos
+ && monster->y + mmov_y == you.y_pos)
{
- monster_attack(i);
- attacked = true;
+ bool isFriendly = mons_friendly(monster);
+ bool attacked = false;
- if (testbits(monster->flags, MF_BATTY))
+ if (!isFriendly)
{
- monster->behaviour = BEH_WANDER;
- monster->target_x = 10 + random2(GXM - 10);
- monster->target_y = 10 + random2(GYM - 10);
+ monster_attack(i);
+ attacked = true;
+
+ if (testbits(monster->flags, MF_BATTY))
+ {
+ monster->behaviour = BEH_WANDER;
+ monster->target_x = 10 + random2(GXM - 10);
+ monster->target_y = 10 + random2(GYM - 10);
+ }
}
- }
- if ((monster->type == MONS_GIANT_SPORE
- || monster->type == MONS_BALL_LIGHTNING)
- && monster->hit_points < 1)
- {
+ if ((monster->type == MONS_GIANT_SPORE
+ || monster->type == MONS_BALL_LIGHTNING)
+ && monster->hit_points < 1)
+ {
- // detach monster from the grid first, so it
- // doesn't get hit by its own explosion (GDL)
- mgrd[monster->x][monster->y] = NON_MONSTER;
+ // detach monster from the grid first, so it
+ // doesn't get hit by its own explosion (GDL)
+ mgrd[monster->x][monster->y] = NON_MONSTER;
- spore_goes_pop(monster);
- monster_cleanup(monster);
- continue;
- }
+ spore_goes_pop(monster);
+ monster_cleanup(monster);
+ continue;
+ }
- if (attacked)
- {
- mmov_x = 0;
- mmov_y = 0;
- continue; //break;
+ if (attacked)
+ {
+ mmov_x = 0;
+ mmov_y = 0;
+ continue; //break;
+ }
}
- }
-
- if (invalid_monster(monster) || mons_is_stationary(monster))
- continue;
- monster_move(monster);
+ if (invalid_monster(monster) || mons_is_stationary(monster))
+ continue;
+ monster_move(monster);
+ }
// reevaluate behaviour, since the monster's
// surroundings have changed (it may have moved,
// or died for that matter. Don't bother for
@@ -4024,6 +4084,7 @@ static bool handle_pickup(monsters *monster)
int hps_gained = 0;
int max_eat = roll_dice( 1, 10 );
int eaten = 0;
+ bool eaten_net = false;
for (item = igrd[monster->x][monster->y];
item != NON_ITEM && eaten < max_eat && hps_gained < 50;
@@ -4041,6 +4102,13 @@ static bool handle_pickup(monsters *monster)
hps_gained += (quant * item_mass( mitm[item] )) / 20 + quant;
eaten += quant;
+
+ if (mons_is_caught(monster) && mitm[item].base_type == OBJ_MISSILES
+ && mitm[item].sub_type == MI_THROWING_NET)
+ {
+ monster->del_ench(ENCH_CAUGHT, true);
+ eaten_net = true;
+ }
}
else
{
@@ -4075,6 +4143,8 @@ static bool handle_pickup(monsters *monster)
mprf(MSGCH_SOUND, "You hear a%s slurping noise.",
monsterNearby ? "" : " distant");
}
+ if (eaten_net)
+ simple_monster_message(monster, " devours the net!");
if (mons_class_flag( monster->type, M_SPLITS ))
{