Skip to content

Commit

Permalink
Strolling Stone: new monster
Browse files Browse the repository at this point in the history
A craggy, mossy beast inhabiting the early dungeon. When it attacks it
will shed plant-based detritus in the form of toadstools and lichen.

A pre-Lair addition to D that requires careful handling and frustrates
the player by littering the battlefield with obstacles.

The tile is a mash-up of the "orb statue", "guardian golem",
"stone_mossy2", with a dash of the old glowing mold.
  • Loading branch information
chucksellick committed Feb 20, 2025
1 parent 55c883e commit b764707
Show file tree
Hide file tree
Showing 13 changed files with 141 additions and 1 deletion.
8 changes: 8 additions & 0 deletions crawl-ref/source/dat/descript/monsters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2883,6 +2883,14 @@ strange machine
A strange mechanical contraption, all hisses and pops. Shadows seem to dance
across its reflective surface.
%%%%
strolling stone

They say a rolling stone gathers no moss; this may be true, but when moving at
more of a sauntering pace they gather all kinds of detritus. A craggy beast
shuffling through the dungeon covered in moss, lichen, and fungus.

When struck it will shed lichen and mushrooms around itself.
%%%%
sun demon

A demonic figure shining with the heat and fury of a fallen star.
Expand Down
18 changes: 18 additions & 0 deletions crawl-ref/source/dat/mons/strolling-stone.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: "strolling stone"
glyph: {char: "9", colour: lightgreen}
flags: [speaks, no_skeleton, unblindable]
resists: {elec: 1, petrify: 1}
genus: golem
holiness: [nonliving]
will: 20
attacks:
- {type: hit, flavour: shed, damage: 13}
hd: 5
hp_10x: 290
ac: 5
ev: 2
shout: moan
intelligence: human
speed: 10
size: large
shape: humanoid
1 change: 1 addition & 0 deletions crawl-ref/source/describe.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5170,6 +5170,7 @@ static string _flavour_base_desc(attack_flavour flavour)
{ AF_AIRSTRIKE, "open air damage" },
{ AF_TRICKSTER, "drain, daze, or confuse" },
{ AF_VEX, "cause vexation" },
{ AF_SHED, "sheds detritus from its body" },
{ AF_PLAIN, "" },
};

Expand Down
9 changes: 8 additions & 1 deletion crawl-ref/source/melee-attack.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3779,6 +3779,7 @@ void melee_attack::mons_apply_attack_flavour()
}
break;
}

case AF_SLEEP:
if (!coinflip())
break;
Expand All @@ -3797,7 +3798,6 @@ void melee_attack::mons_apply_attack_flavour()
defender->put_to_sleep(attacker, random_range(3, 5) * BASELINE_DELAY);
break;


case AF_ALEMBIC:
{
if (needs_message)
Expand Down Expand Up @@ -3831,6 +3831,13 @@ void melee_attack::mons_apply_attack_flavour()
if (--attacker->as_monster()->number == 0)
alembic_brew_potion(*attacker->as_monster());
}

case AF_SHED:
{
if (!defender->is_firewood())
summon_detritus(*attacker->as_monster(), defender->pos());
break;
}
break;

case AF_BOMBLET:
Expand Down
4 changes: 4 additions & 0 deletions crawl-ref/source/mon-death.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3150,6 +3150,10 @@ item_def* monster_die(monster& mons, killer_type killer,
bennu_revive_fineff::schedule(mons.pos(), revives, att, mons.foe,
duel, gozag_bribe);
}
// XX: if the strolling stone *was* an illusion/summoned, unsummon its
// illusory sheddings too...
else if (mons.type == MONS_STROLLING_STONE)
summon_detritus(mons, mons.pos(), true);
}

if (mons_is_tentacle_head(mons_base_type(mons)))
Expand Down
2 changes: 2 additions & 0 deletions crawl-ref/source/mon-enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ enum attack_flavour
AF_TRICKSTER,
AF_SILVER,
AF_VEX,
AF_SHED,
};

// Non-spell "summoning" types to give to monster::mark_summoned(), or
Expand All @@ -182,6 +183,7 @@ enum mon_summon_type
MON_SUMM_WPN_REAP, // Reaping brand reaping
MON_SUMM_CACOPHONY, // Poltergeist ability
MON_SUMM_THRALL, // Vampiric thralls
MON_SUMM_DETRITUS, // Strolling stone shedding
};

#include "mon-flags.h"
Expand Down
1 change: 1 addition & 0 deletions crawl-ref/source/mon-pick-data.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ static const vector<pop_entry> population[] =
{ 6, 9, 1000, PEAK, MONS_BULLFROG },
{ 6, 10, 500, PEAK, MONS_WIGHT },
{ 6, 10, 350, PEAK, MONS_STEAM_DRAGON },
{ 6, 10, 200, PEAK, MONS_STROLLING_STONE},
{ 6, 11, 500, PEAK, MONS_KOBOLD_BRIGAND },
{ 6, 12, 600, PEAK, MONS_ORC_WARRIOR },
{ 7, 11, 500, PEAK, MONS_KILLER_BEE },
Expand Down
2 changes: 2 additions & 0 deletions crawl-ref/source/mon-place.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1403,6 +1403,8 @@ static monster* _place_monster_aux(const mgen_data &mg, const monster *leader,
}
else if (mons_is_child_tentacle(mg.cls))
blame_prefix = "attached to ";
else if (mg.cls == MONS_TOADSTOOL || mg.cls == MONS_WOLF_LICHEN)
blame_prefix = "shed by ";
else
blame_prefix = "created by ";

Expand Down
2 changes: 2 additions & 0 deletions crawl-ref/source/monster-type.h
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,7 @@ enum monster_type // env.mons[].type
MONS_HELLFIRE_MORTAR,
MONS_SPLINTERFROST_BARRICADE,
MONS_SHADOW_TURRET,
MONS_STROLLING_STONE,
#endif

// Demons:
Expand Down Expand Up @@ -1341,6 +1342,7 @@ enum monster_type // env.mons[].type
MONS_ROCK_FISH_SCHOOL,
MONS_SILVER_FISH,
MONS_WOLF_LICHEN,
MONS_STROLLING_STONE,
#endif

NUM_MONSTERS, // used for polymorph
Expand Down
1 change: 1 addition & 0 deletions crawl-ref/source/rltiles/dc-mon.txt
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,7 @@ gargoyle MONS_GARGOYLE
war_gargoyle MONS_WAR_GARGOYLE
molten_gargoyle MONS_MOLTEN_GARGOYLE
%rim 0
strolling_stone MONS_STROLLING_STONE
nargun MONS_NARGUN
%rim 1

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
93 changes: 93 additions & 0 deletions crawl-ref/source/spl-summoning.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2711,6 +2711,99 @@ bool summon_swarm_clone(const monster& agent, coord_def target_pos)
return false;
}

bool summon_detritus(const monster& agent, coord_def target_pos, bool is_death)
{
// Apply pseudo-summon cap
int count_shroom = 0;
int count_lichen = 0;
for (monster_iterator mi; mi; ++mi)
{
if (mi->summoner == agent.mid)
{
if (mi->type == MONS_WOLF_LICHEN)
count_lichen++;
else if (mi->type == MONS_TOADSTOOL)
count_shroom++;
}
}

int num_shroom = 0;
int num_lichen = 0;
const int num_total = is_death ? 4 : 2;

// Create up to 4 max of each type
for (int n=0; n<num_total; n++)
{
const int choice = random_range(0, 2);
if (choice == 1 && num_shroom + count_shroom < 4)
num_shroom++;
else if (choice == 2 && num_lichen + count_lichen < 4)
num_lichen++;
}

int seen_shroom = 0;
int seen_lichen = 0;

int summ_dur = agent.is_summoned()
? agent.as_monster()->get_ench(ENCH_SUMMON).duration : 0;

if (num_shroom > 0)
{
for (int n=0; n<num_shroom; n++)
{
mgen_data mg(MONS_TOADSTOOL, BEH_COPY, target_pos,
_auto_autofoe(&agent), MG_AUTOFOE);
if (agent.is_summoned())
mg.set_summoned(&agent, MON_SUMM_DETRITUS, summ_dur, true);
else
mg.set_summoned(&agent, MON_SUMM_DETRITUS, 0, false, false);
mg.extra_flags |= MF_HARD_RESET | MF_NO_REWARD;

if (monster* spawn = create_monster(mg))
{
if (you.can_see(agent) || you.can_see(*spawn))
seen_shroom++;
}
}
}

if (num_lichen > 0)
{
for (int n=0; n<num_lichen; n++)
{
mgen_data mg(MONS_WOLF_LICHEN, BEH_COPY, target_pos,
_auto_autofoe(&agent), MG_AUTOFOE);
if (agent.is_summoned())
mg.set_summoned(&agent, MON_SUMM_DETRITUS, summ_dur, true);
else
mg.set_summoned(&agent, MON_SUMM_DETRITUS, 0, false, false);
mg.extra_flags |= MF_HARD_RESET | MF_NO_REWARD;

if (monster* spawn = create_monster(mg))
{
if (you.can_see(agent) || you.can_see(*spawn))
seen_lichen++;
}
}
}

if (!seen_shroom && !seen_lichen)
return false;

string seen_what = "";
if (seen_lichen)
seen_what += "lichen";
if (seen_lichen && seen_shroom)
seen_what += " and ";
if (seen_shroom)
seen_what += "toadstools";

mprf("%s sheds %s!", you.can_see(agent) ? agent.name(DESC_THE).c_str() : "Something",
seen_what.c_str());

return true;
}

bool summon_spider(const actor &agent, coord_def pos,
spell_type spell, int pow)
{
Expand Down
1 change: 1 addition & 0 deletions crawl-ref/source/spl-summoning.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ bool summon_hell_out_of_bat(const actor &agent, coord_def pos);
bool summon_spider(const actor &agent, coord_def pos, spell_type spell, int pow);
spret summon_spiders(actor &agent, int pow, bool fail = false);
bool summon_swarm_clone(const monster& agent, coord_def target_pos);
bool summon_detritus(const monster& agent, coord_def target_pos, bool is_death = false);

spret summon_butterflies();

Expand Down

0 comments on commit b764707

Please sign in to comment.