A slime creatures will merge onto an adjacent slime creature if the merge brings it closer to its target, merging only happens when slime creatures aren't wandering, sleeping, or fleeing.
A slime creature will split (if it merged previously) if it is at full hp and is resting or wandering.
I added a hack to make the experienced gained for merged slime creatures approximately equal to killing however many were merged individually, exp from merged slimes may be too low now.
For now the number of slime creatures merged into one J is given explicitly in their description (one-blob slime creature), that should get changed at some point.
Damage and maxHP for merged slime creatures are linear with the number merged, an arbitrary cap of 8 is currently in place.
LL7ZA3RH2A6WGA7YD7XWIZFYG5QNFNSA3UMSUFUMIHHSJZ3SWR4QC
AI4DALP6SCBCSK22RCVR6LWLERKIR7HPK3IGBBKQ426RZNC2V6XAC
BUSA7O6EFBZVAG2RL5T7MD2WTWKOEKKIAAZ2VS4Y3L6ECT4HQR6QC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
YGHUDZATZ5XHYWXPZ7ZMT6OLUDASG4MO2RAWPVJ67V6A3AJVSXUAC
OP6CTAKWCAU64JXQ3USQYR5E5IFHQHNCACII5UMVRXUTZXJQOAZAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
XZTGZ7MOPX7ZOHQ4IQPXOHGUH5WPRNOYAQ6IQOMZDZYNVSAYFTNAC
4SWAT5KCKQV527NKELAXFQ5XA4Q5HONQXD4VBXMUZNPVPQKPCPNAC
GPEJOT73KMACP33IPAKFR5ROGHCOIP22VXZMQNYTGLEA2OSZUM2AC
4LNIHTHZTCOEZEHZ4GW6WCZH4UCDWKK5UVUKEDODEBBS4YH2KONQC
JYEEOUYQ7ZPKOGWUV7VCORBVSOLF2UCBFBH3TR75RGOSS6PNKYUAC
QDTVLBRGHDTRUVT7I3O72K6TMOYAUSAJBZUHGOEFU2RKJNUPWZSQC
KOH7BGYORAFAQ5UL5ACMX4X3JGAQFPNBLMKHAWTVW726S7NVB2KQC
ZNMUUTINYIFCCBFSQDKTTXWXEGAXLDCGPX47NK3Q7NUHRH7S4GXQC
KEANRIMF5CGFVZ2XJYNFPOAKLXOSOJUOVA73IWBWOG576265ERHAC
}
// Calculate slime creature Hp and hd based on how many are merged.
static void _stats_from_blob_count(monsters * slime, float hp_per_blob)
{
int hd_per_blob = 11;
slime->max_hit_points = int(slime->number * hp_per_blob);
slime->hit_points = slime->max_hit_points;
slime->hit_dice = slime->number * hd_per_blob;
}
static bool _split_slime(monsters * thing, coord_def & target)
{
mprf("Splitting slime at pos %d, %d", thing->pos().x, thing->pos().y);
mprf("splitting to %d, %d", target.x, target.y);
// create a new slime
int slime_idx = create_monster(mgen_data(MONS_SLIME_CREATURE,
thing->behaviour,
0,
0,
target,
thing->foe,
MG_FORCE_PLACE));
if(slime_idx == -1)
return false;
monsters * new_slime = &env.mons[slime_idx];
if(!new_slime)
return false;
int split_off = thing->number / 2;
float hp_per_blob = thing->max_hit_points / float(thing->number);
thing->number -= split_off;
new_slime->number = split_off;
_stats_from_blob_count(thing, hp_per_blob);
_stats_from_blob_count(new_slime, hp_per_blob);
return true;
}
static bool _merge_slimes(monsters * initial_slime, monsters * merge_to)
{
mprf("Merging slimes, inital at %d, %d", initial_slime->pos().x, initial_slime->pos().y);
mprf("Merging to %d, %d", merge_to->pos().x, merge_to->pos().y);
merge_to->number += initial_slime->number;
merge_to->max_hit_points += initial_slime->max_hit_points;
merge_to->hit_points += initial_slime->max_hit_points;
merge_to->hit_dice += initial_slime->hit_dice;
// have to 'kill' the slime doing the merging
monster_die(initial_slime, KILL_MISC, NON_MONSTER, true);
return true;
}
bool slime_split_merge(monsters * thing)
{
int compass_idx[8] = {0, 1, 2, 3, 4, 5, 6 ,7};
std::random_shuffle(compass_idx, compass_idx+8);
coord_def origin = thing->pos();
int max_slime_merge = 8;
// We can split if in an 'inactive' state (wandering or sleeping for now)
if (mons_is_sleeping(thing) || mons_is_wandering(thing)
|| thing->foe == MHITNOT)
{
if(thing->number > 1 && thing->hit_points == thing->max_hit_points)
{
// Anywhere we can place a offspring?
// If so split.
for (int i = 0; i < 8; i++)
{
coord_def target=origin + Compass[i];
if(mons_class_can_pass(MONS_SLIME_CREATURE,
env.grid(target))
&& !actor_at(target))
{
return _split_slime(thing, target);
}
} // end adjacent squares check
}// end non singular check
}
// Otherwise see if a merge is viable.
else if(!mons_is_fleeing(thing))
{
// Check for adjacent slime creatures.
for(int i=0;i<8;i++)
{
coord_def target=origin + Compass[i];
monsters * other_thing = monster_at(target);
// We can merge if we find another adjacent slime which isn't
// already at the merge cap and is closer to the target than
// our current position.
if(other_thing
&& other_thing->mons_species() == MONS_SLIME_CREATURE
&& other_thing->attitude == thing->attitude)
{
int new_blob_count = other_thing->number + thing->number;
if(new_blob_count < max_slime_merge
&& grid_distance(thing->target, thing->pos()) >
grid_distance(thing->target, target))
{
return _merge_slimes(thing, other_thing);
}
}
} // end check adjacent
}// end merge check
// Couldn't merge or split
return false;
// The number of hydra heads or manticore attack volleys. Note:
// in older version this field was used for both this and for base_type.
// The number of hydra heads, manticore attack volleys, or merged
// slime creatures. Note: in older version this field was used for
// both this and for base_type.
const int mHD = monster->hit_dice;
const int maxhp = monster->max_hit_points;
int mHD = monster->hit_dice;
int maxhp = monster->max_hit_points;
// Hacks to make merged slime creatures not worth so much
// exp. We will calculate the experience we would get for 1
// blob then just multiply it so that exp is linear with blobs
// merged. -cao
if(monster->mons_species() == MONS_SLIME_CREATURE)
{
mHD /= monster->number;
maxhp /= monster->number;
}
if(mon.mons_species() == MONS_SLIME_CREATURE && desc != DESC_DBNAME)
{
if (mon.number < 11)
{
const char* cardinals[] = {"one", "two", "three", "four", "five",
"six", "seven", "eight", "nine", "ten"};
result += cardinals[mon.number - 1];
}
else
result += make_stringf("%d", mon.number);