diff options
author | Charles Otto <ottochar@gmail.com> | 2009-10-24 18:34:36 -0400 |
---|---|---|
committer | Charles Otto <ottochar@gmail.com> | 2009-10-30 20:31:27 -0400 |
commit | d0f35e86de825119d5fa255f6075a55a89f2f20b (patch) | |
tree | 577616aaf6a9dc4e6a3f8f3e632a095343ef8551 | |
parent | 387e5d2db125d6306f6eed6901ce3b504ce44072 (diff) | |
download | crawl-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.cc | 40 | ||||
-rw-r--r-- | crawl-ref/source/monplace.cc | 4 | ||||
-rw-r--r-- | crawl-ref/source/monplace.h | 5 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 15 | ||||
-rw-r--r-- | crawl-ref/source/mstuff2.cc | 124 | ||||
-rw-r--r-- | crawl-ref/source/mstuff2.h | 1 |
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); |