Increase royal jelly movement speed, hp and attack damage. The royal jelly now spits out high-level jellies when it takes a high-damage hit of any kind. No experience for the expelled jellies, given that they're technically part of the royal jelly, and the royal jelly already gives a heap of xp.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3985 c06c8d41-db1a-0410-9941-cceddc491573
22MF6OUN62WDBJR5QFNJTKU7Q5TIQ76XWCEIRBFWAZDMZUSKJGCAC
ITA3XNJBFNQONTIPJYRSVAOY55PUWSYYEZXZTVBQBH5XA3A5MNJAC
M2EUGZPKR6XTZSLQYDO7CDBBR2WPPMCBIBKJSZW5P7KYUOUPZSZQC
2WVP47RBNL5OVYMAZH7TKRYD7F2TGSZ5X74PWVGAYCQP26G3JUHQC
RC6L3CIBLJEH4GWRFD7UQNGI6PZT74FRUVOYHSAN2XCC74NZUASQC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
AOAJ6D3OKSELEYKAT55XCVU5LYJ7SMCZKC6DIEGLLB3TF2LEENWQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
7AREIGBWRJPQI7N7UMSXYWGOI5D6OFUKX656PX3GOZVY3ALY75BAC
3GSAVTNKEG45AT2U734R5STSRP22WJZL3H6KUFRUWCIA6A4CZE5QC
4D4TJWFTQ74TBNJYW42CP3UYIQT4Q22IO7N34UOBUE3Y6RICHEJAC
B62ICMDTN5V7R7RBL4JALFVKEMVOOVLRSJASRNYS6CGFWBEEF5JQC
3C2VE43SHCSBY4LTRTFYFLIPRWFUN6DXU6D34QVWDQTSNRBUFG7AC
ID373JATLMWAY526Q6Q5FXHRNFWMEOFXPHGPAUUY5OAMPFDN5SJAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
RBAGQ2PB7V5YAM5KSHSZR2E3MLKDSRVM5XYGI2TIXP5QMVBOQHDQC
TVC7W7C2XKBQSD2IJFMWFVGXZAOD4EUOW43NAQTOF5KFMAUOJABQC
3WHI3KM43ZCN4ITJLFQQBQBC4OJPRS7QTBPIQ6QBCUVKRSK476SAC
OSGS3PH2L5CBTDVZCZS6OCFQNA4A7RMEXBYJQB7DDZBYYJW7QSSAC
MJWFTUS66PTCNEYXEJA3CUJFXNWXIKDD6H3V24PW7HK64NSVOFSAC
MG6LLF3XYCOEBQRX7TJ4MUTKM3IROYWUMZGCMYVW4TGDG36CJMJQC
NLQNXH3SVJ52CWXEV35FSSZP32VHC4QFGN3HINF4KO5GZHZMOBKQC
R22TTMI6WXWULC7ODKFF3QCB7MOTETQQ6IR4BUCUPOCQKQNCTT5AC
X5WLJCJVW55SXZVP7IKP7ADCJIGNKN4PKAXFECVR6TNK7XSMZR7QC
QKGDOYIYKE6B36ION5O2DRW65DWWPZMYNWJVH7LJJ7FPGGM2MYAQC
HFEFKHVV2ULXS6ZEFNX6ZXXUJKME5L2PITQ3VRTKMRUOU3DHXXWQC
}
static int _monster_natural_regen_roll(monsters *monster)
{
// A HD divider ranging from 3 (at 1 HD) to 1 (at 8 HD).
int divider =
std::max(div_rand_round(15 - monster->hit_dice, 4), 1);
// The undead have a harder time regenerating.
switch (monster->holiness())
{
// The undead don't regenerate easily.
case MH_UNDEAD:
divider *= 4;
break;
// And golems have it worse.
case MH_NONLIVING:
divider *= 5;
break;
default:
break;
}
const int regen_rate =
std::max(div_rand_round(monster->hit_dice, divider), 1);
return (random2(25) < regen_rate);
&& (grd[monster->x][monster->y] == DNGN_LAVA
|| (env.cgrid(monster->pos()) != EMPTY_CLOUD
&& env.cloud[env.cgrid(monster->pos())].type
== CLOUD_FIRE)))
&& (grd(monster->pos()) == DNGN_LAVA
|| cloud_type_at(monster->pos()) == CLOUD_FIRE))
static dungeon_feature_type _monster_habitat_feature(int mtype)
{
return ((mtype == RANDOM_MONSTER) ? DNGN_FLOOR
: habitat2grid( mons_habitat_by_type(mtype) ));
}
class newmons_square_find : public travel_pathfind
{
private:
dungeon_feature_type grid_wanted;
coord_def start;
int maxdistance;
int best_distance;
int nfound;
public:
// Terrain that we can't spawn on, but that we can skip through.
std::set<dungeon_feature_type> passable;
public:
newmons_square_find(dungeon_feature_type grdw,
const coord_def &pos,
int maxdist = 0)
: grid_wanted(grdw), start(pos), maxdistance(maxdist),
best_distance(0), nfound(0)
{
}
coord_def pathfind()
{
set_floodseed(start);
return travel_pathfind::pathfind(RMODE_EXPLORE);
}
bool path_flood(const coord_def &c, const coord_def &dc)
{
if (best_distance && traveled_distance > best_distance)
return (true);
if (!in_bounds(dc)
|| (maxdistance > 0 && traveled_distance > maxdistance))
{
return (false);
}
if (!grid_compatible(grid_wanted, grd(dc), true))
{
if (passable.find(grd(dc)) != passable.end())
good_square(dc);
return (false);
}
if (mgrd(dc) == NON_MONSTER && dc != you.pos()
&& one_chance_in(++nfound))
{
greedy_dist = traveled_distance;
greedy_place = dc;
best_distance = traveled_distance;
}
else
{
good_square(dc);
}
return (false);
}
};
/*
* Finds a square for a monster of the given class, pathfinding
* through only contiguous squares of habitable terrain.
*/
coord_def find_newmons_square_contiguous(monster_type mons_class,
const coord_def &start,
int distance)
{
newmons_square_find nmfind(_monster_habitat_feature(mons_class),
start, distance);
const coord_def p = nmfind.pathfind();
return (in_bounds(p)? p : coord_def(-1, -1));
}
}
static inline monster_type _royal_jelly_ejectable_monster()
{
return static_cast<monster_type>(
random_choose( MONS_ACID_BLOB,
MONS_AZURE_JELLY,
MONS_DEATH_OOZE,
-1 ) );
}
void monsters::react_to_damage(int damage)
{
// The royal jelly objects to taking damage and will SULK. :-)
if (type == MONS_ROYAL_JELLY && alive()
&& damage > 8 && random2(50) < damage)
{
const int tospawn =
1 + random2avg(1 + std::min((damage - 8) / 8, 5), 2);
mprf(MSGCH_DIAGNOSTICS, "Trying to spawn %d jellies.", tospawn);
const beh_type sbehaviour = SAME_ATTITUDE(this);
int spawned = 0;
for (int i = 0; i < tospawn; ++i)
{
const monster_type jelly = _royal_jelly_ejectable_monster();
coord_def jpos = find_newmons_square_contiguous(jelly, pos());
if (!in_bounds(jpos))
continue;
const int nmons =
mons_place( jelly, sbehaviour, foe, true, jpos.x, jpos.y,
you.level_type, PROX_ANYWHERE, MONS_PROGRAM_BUG,
0, false );
if (nmons != -1 && nmons != NON_MONSTER)
{
// Don't allow milking the royal jelly.
menv[nmons].flags |= MF_CREATED_FRIENDLY;
spawned++;
}
}
const bool needs_message =
spawned && mons_near(this) && player_monster_visible(this);
if (needs_message)
{
const std::string mname = name(DESC_CAP_THE);
mprf("%s shudders%s.", mname.c_str(),
spawned >= 5 ? " alarmingly" :
spawned >= 3 ? " violently" :
spawned > 1 ? " vigorously" : "");
if (spawned == 1)
mprf("%s spits out another jelly.", mname.c_str());
else
mprf("%s spits out %s more jellies.",
mname.c_str(),
number_in_words(spawned).c_str());
}
}