summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCharles Otto <ottochar@gmail.com>2009-10-24 18:34:36 -0400
committerCharles Otto <ottochar@gmail.com>2009-10-30 20:31:27 -0400
commitd0f35e86de825119d5fa255f6075a55a89f2f20b (patch)
tree577616aaf6a9dc4e6a3f8f3e632a095343ef8551
parent387e5d2db125d6306f6eed6901ce3b504ce44072 (diff)
downloadcrawl-ref-d0f35e86de825119d5fa255f6075a55a89f2f20b.tar.gz
crawl-ref-d0f35e86de825119d5fa255f6075a55a89f2f20b.zip
Preliminary support for slime creatures merging and splitting.
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.
-rw-r--r--crawl-ref/source/mon-util.cc40
-rw-r--r--crawl-ref/source/monplace.cc4
-rw-r--r--crawl-ref/source/monplace.h5
-rw-r--r--crawl-ref/source/monstuff.cc15
-rw-r--r--crawl-ref/source/mstuff2.cc124
-rw-r--r--crawl-ref/source/mstuff2.h1
6 files changed, 183 insertions, 6 deletions
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 7e8785814b..3e8ab4d865 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -1144,6 +1144,12 @@ mon_attack_def mons_attack_spec(const monsters *mon, int attk_number)
attk.flavour = RANDOM_ELEMENT(flavours);
}
+ // Slime creature attacks are multiplied by the number merged.
+ if(mon->mons_species() == MONS_SLIME_CREATURE)
+ {
+ attk.damage *= mon->number;
+ }
+
return (zombified ? downscale_zombie_attack(mon, attk) : attk);
}
@@ -1621,8 +1627,18 @@ int exper_value(const monsters *monster)
// These four are the original arguments.
const int mclass = monster->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;
+ }
// These are some values we care about.
const int speed = mons_base_speed(monster);
@@ -1737,6 +1753,13 @@ int exper_value(const monsters *monster)
x_val /= 10;
}
+ // Slime creature exp hack part 2, scale exp back up by the
+ // number of blobs merged. -cao
+ if(monster->mons_species() == MONS_SLIME_CREATURE)
+ {
+ x_val *= monster->number;
+ }
+
// Reductions for big values. -- bwr
if (x_val > 100)
x_val = 100 + ((x_val - 100) * 3) / 4;
@@ -2182,6 +2205,19 @@ static std::string _str_monam(const monsters& mon, description_level_type desc,
break;
}
+ 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);
+
+ result += "-blob ";
+ }
// Done here to cover cases of undead versions of hydras.
if (mons_species(nametype) == MONS_HYDRA
&& mon.number > 0 && desc != DESC_DBNAME)
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index be27711eef..a340ff226a 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -1221,6 +1221,10 @@ static int _place_monster_aux(const mgen_data &mg,
if (mg.cls == MONS_MANTICORE)
menv[id].number = 8 + random2(9);
+ // Slime creatures start off as only a single merged blob.
+ if (mg.cls == MONS_SLIME_CREATURE)
+ menv[id].number = 1;
+
// Set attitude, behaviour and target.
menv[id].attitude = ATT_HOSTILE;
menv[id].behaviour = mg.behaviour;
diff --git a/crawl-ref/source/monplace.h b/crawl-ref/source/monplace.h
index eb30a97db2..709d147c57 100644
--- a/crawl-ref/source/monplace.h
+++ b/crawl-ref/source/monplace.h
@@ -152,8 +152,9 @@ struct mgen_data
// indicate whose priest they are.
god_type god;
- // 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.
int number;
// The colour of the monster.
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index c6dcc55c7b..0fce237d74 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -5883,6 +5883,13 @@ static bool _handle_special_ability(monsters *monster, bolt & beem)
used = ugly_thing_mutate(monster, true);
break;
+ case MONS_SLIME_CREATURE:
+ // Slime creatures may split or merge depending on the situation
+ used = slime_split_merge(monster);
+ if(!monster->alive())
+ return true;
+ break;
+
case MONS_ORC_KNIGHT:
case MONS_ORC_WARLORD:
case MONS_SAINT_ROKA:
@@ -7843,7 +7850,9 @@ static void _handle_monster_move(monsters *monster)
if (!mons_is_sleeping(monster) && !mons_is_wandering(monster)
// Berserking monsters are limited to running up and
// hitting their foes.
- && !monster->has_ench(ENCH_BERSERK))
+ && !monster->has_ench(ENCH_BERSERK)
+ // Slime creatures can split while wandering or resting
+ || monster->type == MONS_SLIME_CREATURE)
{
bolt beem;
@@ -7855,7 +7864,9 @@ static void _handle_monster_move(monsters *monster)
mons_friendly(monster) || monster->near_foe();
// Prevents unfriendlies from nuking you from offscreen.
// How nice!
- if (friendly_or_near || monster->type == MONS_TEST_SPAWNER)
+ // Slime creatures can split when offscreen
+ if (friendly_or_near || monster->type == MONS_TEST_SPAWNER
+ || monster->type == MONS_SLIME_CREATURE)
{
// [ds] Special abilities shouldn't overwhelm spellcasting
// in monsters that have both. This aims to give them both
diff --git a/crawl-ref/source/mstuff2.cc b/crawl-ref/source/mstuff2.cc
index 2c6bc1fe7d..6dcf1f66a3 100644
--- a/crawl-ref/source/mstuff2.cc
+++ b/crawl-ref/source/mstuff2.cc
@@ -2588,6 +2588,130 @@ bool ugly_thing_mutate(monsters *ugly, bool proximity)
return (false);
}
+// 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;
+}
+
bool orc_battle_cry(monsters *chief)
{
const actor *foe = chief->get_foe();
diff --git a/crawl-ref/source/mstuff2.h b/crawl-ref/source/mstuff2.h
index 70238e5835..e5f50f1f42 100644
--- a/crawl-ref/source/mstuff2.h
+++ b/crawl-ref/source/mstuff2.h
@@ -28,6 +28,7 @@ bool monster_random_space(monster_type mon, coord_def& target,
bool forbid_sanctuary = false);
void monster_teleport(monsters *monster, bool instan, bool silent = false);
bool ugly_thing_mutate(monsters *ugly, bool proximity = false);
+bool slime_split_merge(monsters * thing);
bool orc_battle_cry(monsters *chief);
bool orange_statue_effects(monsters *mons);
bool silver_statue_effects(monsters *mons);