summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authorCharles Otto <ottochar@gmail.com>2009-11-13 00:51:56 -0500
committerCharles Otto <ottochar@gmail.com>2009-11-13 00:51:56 -0500
commite7d888537c4d178a98e2ef1727a84d5132655d6c (patch)
tree79fc6a8cb3a521b7c4d6a9f8fb761a12c7d6ed23 /crawl-ref
parent4a7b398e339f0b55ae3ce579a02c81c2c281216d (diff)
parent8075717d132ff61257a8836ce7854f71f1eb05f8 (diff)
downloadcrawl-ref-e7d888537c4d178a98e2ef1727a84d5132655d6c.tar.gz
crawl-ref-e7d888537c4d178a98e2ef1727a84d5132655d6c.zip
Merge spore experiments branch.
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/beam.cc30
-rw-r--r--crawl-ref/source/godabil.cc3
-rw-r--r--crawl-ref/source/mon-abil.cc105
-rw-r--r--crawl-ref/source/mon-abil.h4
-rw-r--r--crawl-ref/source/mon-act.cc4
-rw-r--r--crawl-ref/source/mon-data.h2
-rw-r--r--crawl-ref/source/mon-info.cc3
-rw-r--r--crawl-ref/source/mon-place.cc6
-rw-r--r--crawl-ref/source/mon-stuff.cc6
-rw-r--r--crawl-ref/source/monster.cc33
-rw-r--r--crawl-ref/source/view.cc9
11 files changed, 181 insertions, 24 deletions
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index b5282066f7..973962a6af 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -2555,6 +2555,11 @@ int mons_adjust_flavoured(monsters *monster, bolt &pbolt, int hurted,
}
break;
+ case BEAM_SPORE:
+ if (monster->type == MONS_BALLISTOMYCETE)
+ hurted = 0;
+ break;
+
default:
break;
}
@@ -3101,9 +3106,30 @@ void bolt::affect_ground()
&& mons_class_can_pass(MONS_BALLISTOMYCETE, env.grid(pos()))
&& !actor_at(pos()))
{
+ beh_type beh;
// Half the fungi in arena mode are friendly.
- beh_type beh = (crawl_state.arena && coinflip()) ? BEH_FRIENDLY
- : BEH_HOSTILE;
+ if(crawl_state.arena)
+ {
+ beh = coinflip() ? BEH_FRIENDLY : BEH_HOSTILE;
+ }
+ else
+ {
+ switch(this->attitude)
+ {
+ case ATT_NEUTRAL:
+ beh = BEH_NEUTRAL;
+ break;
+
+ case ATT_FRIENDLY:
+ case ATT_GOOD_NEUTRAL:
+ beh = BEH_GOOD_NEUTRAL;
+ break;
+
+ default:
+ beh = BEH_HOSTILE;
+ break;
+ }
+ }
int rc = create_monster(mgen_data(MONS_BALLISTOMYCETE,
beh,
diff --git a/crawl-ref/source/godabil.cc b/crawl-ref/source/godabil.cc
index 6af4394a09..69986ec4be 100644
--- a/crawl-ref/source/godabil.cc
+++ b/crawl-ref/source/godabil.cc
@@ -1133,9 +1133,6 @@ bool evolve_flora()
current_plant->del_ench(ENCH_SLOWLY_DYING);
current_plant->del_ench(ENCH_SPORE_PRODUCTION);
- if (current_plant->mons_species() == MONS_BALLISTOMYCETE)
- current_plant->add_ench(ENCH_SPORE_PRODUCTION);
-
// Maybe we can upgrade it again?
if (_possible_evolution(current_plant, temp_conversion)
&& temp_conversion.cost <= points)
diff --git a/crawl-ref/source/mon-abil.cc b/crawl-ref/source/mon-abil.cc
index 43118781d1..9d53edc726 100644
--- a/crawl-ref/source/mon-abil.cc
+++ b/crawl-ref/source/mon-abil.cc
@@ -1388,4 +1388,109 @@ void mon_nearby_ability(monsters *monster)
}
}
+// When giant spores move (while wandering) maybe place a spore on the
+// square they move off of.
+void ballisto_on_move(monsters * monster, const coord_def & position)
+{
+ if (monster->type == MONS_GIANT_SPORE)
+ {
+ // The number field is used as a cooldown timer for this behavior.
+ if (monster->number <= 0)
+ {
+ if (one_chance_in(4))
+ {
+ beh_type attitude = SAME_ATTITUDE(monster);
+ if(!crawl_state.arena && attitude == BEH_FRIENDLY)
+ {
+ attitude = BEH_GOOD_NEUTRAL;
+ }
+ int rc = create_monster(mgen_data(MONS_BALLISTOMYCETE,
+ attitude,
+ 0,
+ 0,
+ position,
+ MHITNOT,
+ MG_FORCE_PLACE));
+
+ if (rc != -1 && you.can_see(&env.mons[rc]))
+ mprf("A ballistomycete grows in the wake of the spore.");
+
+ monster->number = 40;
+ }
+ }
+ else
+ {
+ monster->number--;
+ }
+
+ }
+}
+
+void activate_ballistomycetes( monsters * monster)
+{
+ if(!monster || monster->type != MONS_BALLISTOMYCETE && monster->type != MONS_GIANT_SPORE)
+ return;
+
+ bool activated_others = false;
+ int seen_others = 0;
+ for(int i=0; i < int(env.mons.size()); ++i)
+ {
+ if(i != monster->mindex()
+ && env.mons[i].alive()
+ && env.mons[i].type == MONS_BALLISTOMYCETE)
+ {
+ env.mons[i].number++;
+ // 0 -> 1 means the ballisto moves onto the faster spawn
+ // timer and changes color
+ if(env.mons[i].number == 1)
+ {
+ env.mons[i].colour = LIGHTRED;
+ // Reset the spore production timer.
+ env.mons[i].del_ench(ENCH_SPORE_PRODUCTION, false);
+ env.mons[i].add_ench(ENCH_SPORE_PRODUCTION);
+ activated_others = true;
+ if(you.can_see(&env.mons[i]))
+ seen_others++;
+ }
+ }
+ }
+
+ // How to do messaging? Message on kill no matter what, only if you see
+ // other ballistos get angry, only if other ballistos get angry
+ // (seen or not). Also need a message if a ballisto suddenly becomes
+ // angry
+ if(mons_near(monster) && activated_others)
+ mprf("You feel ballistomycets on the level are angry now?");
+ else if (seen_others > 0)
+ mprf("The ballistomycete appears angry...");
+}
+
+void deactivate_ballistos()
+{
+ for(unsigned i=0;i < env.mons.size(); i++)
+ {
+ if(env.mons[i].alive()
+ && env.mons[i].type == MONS_BALLISTOMYCETE)
+ {
+ monsters * temp = &env.mons[i];
+ // Decrease the count and maybe become inactive
+ // again
+ if(temp->number)
+ {
+ temp->number--;
+ if(temp->number == 0)
+ {
+ temp->colour = MAGENTA;
+ temp->del_ench(ENCH_SPORE_PRODUCTION);
+ //temp->add_ench(ENCH_SPORE_PRODUCTION);
+ if(you.can_see(temp))
+ mprf("A nearby ballistomycete calms down.");
+ }
+ }
+
+
+ }
+ }
+}
+
diff --git a/crawl-ref/source/mon-abil.h b/crawl-ref/source/mon-abil.h
index 527f71dc3e..810ccd43f4 100644
--- a/crawl-ref/source/mon-abil.h
+++ b/crawl-ref/source/mon-abil.h
@@ -16,4 +16,8 @@ void mon_nearby_ability(monsters *monster);
bool ugly_thing_mutate(monsters *ugly, bool proximity = false);
bool slime_split_merge(monsters *thing);
+void ballisto_on_move(monsters * monster, const coord_def & pos);
+void activate_ballistomycetes( monsters * monster);
+void deactivate_ballistos();
+
#endif
diff --git a/crawl-ref/source/mon-act.cc b/crawl-ref/source/mon-act.cc
index d9bce0dbfd..f699d7578e 100644
--- a/crawl-ref/source/mon-act.cc
+++ b/crawl-ref/source/mon-act.cc
@@ -3104,10 +3104,14 @@ static bool _do_move_monster(monsters *monster, const coord_def& delta)
}
mgrd(monster->pos()) = NON_MONSTER;
+ coord_def old_pos = monster->pos();
+
monster->set_position(f);
mgrd(monster->pos()) = monster_index(monster);
+ ballisto_on_move(monster, old_pos);
+
monster->check_redraw(monster->pos() - delta);
monster->apply_location_effects(monster->pos() - delta);
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index 38cf14ff50..dc677f3413 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -713,7 +713,7 @@ static monsterentry mondata[] = {
},
{
- MONS_BALLISTOMYCETE, 'f', LIGHTRED, "ballistomycete",
+ MONS_BALLISTOMYCETE, 'f', MAGENTA, "ballistomycete",
M_STATIONARY,
MR_RES_POISON,
0, 10, MONS_FUNGUS, MONS_FUNGUS, MH_PLANT, MAG_IMMUNE,
diff --git a/crawl-ref/source/mon-info.cc b/crawl-ref/source/mon-info.cc
index 659aa1cb7d..d32b8466d1 100644
--- a/crawl-ref/source/mon-info.cc
+++ b/crawl-ref/source/mon-info.cc
@@ -115,6 +115,9 @@ bool monster_info::less_than(const monster_info& m1,
if (m1type == MONS_SLIME_CREATURE)
return (m1.m_mon->number > m2.m_mon->number);
+ if (m1type == MONS_BALLISTOMYCETE)
+ return ((m1.m_mon->number > 0) > (m2.m_mon->number > 0));
+
if (zombified)
{
// Because of the type checks above, if one of the two is zombified, so
diff --git a/crawl-ref/source/mon-place.cc b/crawl-ref/source/mon-place.cc
index c326c359d8..dbf488e6a5 100644
--- a/crawl-ref/source/mon-place.cc
+++ b/crawl-ref/source/mon-place.cc
@@ -1163,12 +1163,6 @@ static int _place_monster_aux(const mgen_data &mg,
mon->add_ench(ENCH_SLOWLY_DYING);
}
- if (mg.cls == MONS_BALLISTOMYCETE)
- {
- // This enchantment causes giant spore production.
- mon->add_ench(ENCH_SPORE_PRODUCTION);
- }
-
if (monster_can_submerge(mon, grd(fpos)) && !one_chance_in(5))
mon->add_ench(ENCH_SUBMERGED);
diff --git a/crawl-ref/source/mon-stuff.cc b/crawl-ref/source/mon-stuff.cc
index 5cf5677528..0e8a3b436f 100644
--- a/crawl-ref/source/mon-stuff.cc
+++ b/crawl-ref/source/mon-stuff.cc
@@ -33,6 +33,7 @@
#include "kills.h"
#include "message.h"
#include "misc.h"
+#include "mon-abil.h"
#include "mon-behv.h"
#include "mon-iter.h"
#include "mon-place.h"
@@ -1093,6 +1094,7 @@ static bool _spore_goes_pop(monsters *monster, killer_type killer,
beam.thrower = crawl_state.arena ? KILL_MON
: monster->attitude == ATT_FRIENDLY ? KILL_YOU : KILL_MON;
beam.aux_source.clear();
+ beam.attitude = monster->attitude;
if (YOU_KILL(killer))
beam.aux_source = "set off by themselves";
@@ -1163,6 +1165,7 @@ static bool _spore_goes_pop(monsters *monster, killer_type killer,
// FIXME: show_more == mons_near(monster)
beam.explode();
+ activate_ballistomycetes(monster);
// Monster died in explosion, so don't re-attach it to the grid.
return (true);
}
@@ -1498,6 +1501,9 @@ int monster_die(monsters *monster, killer_type killer,
you.remove_beholder(monster);
+ if(monster->type == MONS_BALLISTOMYCETE)
+ activate_ballistomycetes(monster);
+
// Clear auto exclusion now the monster is killed -- if we know about it.
if (mons_near(monster) || wizard)
remove_auto_exclude(monster);
diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc
index 0c963631c7..869e65ce68 100644
--- a/crawl-ref/source/monster.cc
+++ b/crawl-ref/source/monster.cc
@@ -2158,6 +2158,11 @@ static std::string _str_monam(const monsters& mon, description_level_type desc,
result += cardinals[mon.number];
}
+ if (mon.type == MONS_BALLISTOMYCETE && desc != DESC_DBNAME)
+ {
+ result += mon.number ? "active " : "";
+ }
+
// Done here to cover cases of undead versions of hydras.
if (mons_species(nametype) == MONS_HYDRA
&& mon.number > 0 && desc != DESC_DBNAME)
@@ -4986,22 +4991,23 @@ void monsters::apply_enchantment(const mon_enchant &me)
break;
case ENCH_SPORE_PRODUCTION:
- // Very low chance of actually making a spore on each turn.
- if(one_chance_in(5000))
+
+ // Reduce the timer, if that means we lose the enchantment then
+ // spawn a spore and re-add the enchantment
+ if(decay_enchantment(me))
{
+ // Search for an open adjacent square to place a spore on
int idx[] = {0, 1, 2, 3, 4, 5, 6, 7};
std::random_shuffle(idx, idx + 8);
for (unsigned i = 0; i < 8; ++i)
{
coord_def adjacent = this->pos() + Compass[idx[i]];
+
if (mons_class_can_pass(MONS_GIANT_SPORE, env.grid(adjacent))
- && !actor_at(adjacent))
+ && !actor_at(adjacent))
{
- beh_type created_behavior = BEH_HOSTILE;
-
- if (this->attitude == ATT_FRIENDLY)
- created_behavior = BEH_FRIENDLY;
+ beh_type created_behavior = SAME_ATTITUDE(this);
int rc = create_monster(mgen_data(MONS_GIANT_SPORE,
created_behavior,
@@ -5015,14 +5021,21 @@ void monsters::apply_enchantment(const mon_enchant &me)
if (rc != -1)
{
env.mons[rc].behaviour = BEH_WANDER;
+ env.mons[rc].number = 20;
if (observe_cell(adjacent) && observe_cell(pos()))
mpr("A nearby fungus spawns a giant spore.");
+
+ deactivate_ballistos();
}
break;
}
}
+ // Re=add the enchantment (this resets the spore production
+ // timer).
+ this->add_ench(ENCH_SPORE_PRODUCTION);
}
+
break;
case ENCH_GLOWING_SHAPESHIFTER: // This ench never runs out!
@@ -6044,6 +6057,12 @@ int mon_enchant::calc_duration(const monsters *mons,
// of this function is excessive for toadstools. -cao
return (2 * FRESHEST_CORPSE + random2(10))
* speed_to_duration(mons->speed) * mons->speed / 10;
+ case ENCH_SPORE_PRODUCTION:
+ // The duration of the spore production timer depends on the color
+ // of the fungus
+ cturn = mons->number ? 150 : 1500;
+ break;
+
case ENCH_ABJ:
if (deg >= 6)
cturn = 1000 / _mod_speed(10, mons->speed);
diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc
index 092ac802d3..648141b7a3 100644
--- a/crawl-ref/source/view.cc
+++ b/crawl-ref/source/view.cc
@@ -133,14 +133,13 @@ void monster_grid_updates()
handle_monster_shouts(*mi);
}
+ fedhas_neutralise(monster);
if (!mi->visible_to(&you))
continue;
- good_god_follower_attitude_change(*mi);
- beogh_follower_convert(*mi);
- slime_convert(*mi);
- fedhas_neutralise(*mi);
-
+ good_god_follower_attitude_change(monster);
+ beogh_follower_convert(monster);
+ slime_convert(monster);
// XXX: Probably quite hackish. Allows for monsters going berserk when
// they see the player. Currently only used for Duvessa, see the
// function _elven_twin_dies in mon-stuff.cc.