diff options
Diffstat (limited to 'crawl-ref/source')
-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); |