Turn +Rats into *Rats
authorNicholas Feinberg <pleasingfung@gmail.com>
Sat, 1 Aug 2020 05:55:40 +0000 (22:55 -0700)
committerNicholas Feinberg <pleasingfung@gmail.com>
Sat, 1 Aug 2020 05:55:40 +0000 (22:55 -0700)
The Ratskin Cloak is yet another of Crawl's many, many very powerful
items that demands considerable micromanagement to unlock its power.
Some items offer a lot of fun when micromanaged, but this big bag o'
rats doesn't quite get there.

Change it from an activated ability to instead spawn rats when the
player is hit. Goal is to have bonus rats as a 'sometimes thing'.
Current odds are somewhat arbitrary but seem to play OK.

crawl-ref/source/ability-type.h
crawl-ref/source/ability.cc
crawl-ref/source/art-data.txt
crawl-ref/source/dat/descript/unrand.txt
crawl-ref/source/item-name.cc
crawl-ref/source/item-prop.cc
crawl-ref/source/ouch.cc
crawl-ref/source/rltiles/UNUSED/gui/evoke_ratskin.png [moved from crawl-ref/source/rltiles/gui/abilities/evoke_ratskin.png with 100% similarity]
crawl-ref/source/rltiles/dc-abilities.txt
crawl-ref/source/tilepick.cc

index 593bf6f..bfdd972 100644 (file)
@@ -75,8 +75,8 @@ enum ability_type
 #if TAG_MAJOR_VERSION == 34
     ABIL_EVOKE_TELEPORT_CONTROL,
     ABIL_EVOKE_TWISTER,
-#endif
     ABIL_EVOKE_RATSKIN,
+#endif
     ABIL_EVOKE_THUNDER,
     ABIL_MAX_EVOKE = ABIL_EVOKE_THUNDER,
 
index c5a3953..8ed1f17 100644 (file)
@@ -340,8 +340,6 @@ static const ability_def Ability_List[] =
       1, 0, 0, {fail_basis::evo, 40, 2}, abflag::none },
     { ABIL_EVOKE_FOG, "Evoke Fog",
       2, 0, 0, {fail_basis::evo, 50, 2}, abflag::none },
-    { ABIL_EVOKE_RATSKIN, "Evoke Ratskin",
-      3, 0, 0, {fail_basis::evo, 50, 2}, abflag::none },
     { ABIL_EVOKE_THUNDER, "Evoke Thunderclouds",
       5, 0, 0, {fail_basis::evo, 60, 2}, abflag::none },
 
@@ -2203,21 +2201,6 @@ static spret _do_ability(const ability_def& abil, bool fail)
         big_cloud(random_smoke_type(), &you, you.pos(), 50, 8 + random2(8));
         break;
 
-    case ABIL_EVOKE_RATSKIN: // ratskin cloak
-        fail_check();
-        mpr("The rats of the Dungeon answer your call.");
-
-        for (int i = 0; i < (coinflip() + 1); ++i)
-        {
-            monster_type mon = coinflip() ? MONS_HELL_RAT : MONS_RIVER_RAT;
-
-            mgen_data mg(mon, BEH_FRIENDLY, you.pos(), MHITYOU);
-            if (monster *m = create_monster(mg))
-                m->add_ench(mon_enchant(ENCH_FAKE_ABJURATION, 3));
-        }
-
-        break;
-
     case ABIL_EVOKE_THUNDER: // robe of Clouds
         fail_check();
         mpr("The folds of your robe billow into a mighty storm.");
@@ -3542,13 +3525,6 @@ vector<talent> your_talents(bool check_confused, bool include_unusable)
         _add_talent(talents, ABIL_EVOKE_FOG, check_confused);
     }
 
-    if (player_equip_unrand(UNRAND_RATSKIN_CLOAK)
-        && !you.get_mutation_level(MUT_NO_ARTIFICE)
-        && !you.get_mutation_level(MUT_NO_LOVE))
-    {
-        _add_talent(talents, ABIL_EVOKE_RATSKIN, check_confused);
-    }
-
     if (player_equip_unrand(UNRAND_RCLOUDS)
         && !you.get_mutation_level(MUT_NO_ARTIFICE))
     {
index 4de477f..6354ccf 100644 (file)
@@ -936,7 +936,7 @@ PLUS:     +2
 COLOUR:   ETC_BEOGH
 TILE:     urand_ratskin_cloak
 TILE_EQ:  ratskin
-INSCRIP:  +Rats
+INSCRIP:  *Rats
 STR:      -1
 INT:      -1
 DEX:      1
index 9022d17..82a6857 100644 (file)
@@ -426,12 +426,9 @@ A phosphorescent cloak, woven of pure light beams.
 %%%%
 ratskin cloak
 
-A cloak stitched from the hides of hundreds of hell rats, by an enchantress
-with a magic loom and too much time on her hands. It provides excellent
-protection from rats of all kinds.
-
-It can be evoked to summon rats from the Dungeon to accompany the wearer,
-for a time.
+A cloak stitched from the hides of hundreds of hell rats by an enchantress with
+far too much time on her hands. Blows inflicted on the wearer will occasionally
+provoke rats concealed beneath the cloak to scurry out and assist.
 %%%%
 shield of the Gong
 
index f6b24d9..6a24bd0 100644 (file)
@@ -2788,6 +2788,14 @@ bool is_dangerous_item(const item_def &item, bool temp)
         return item.sub_type == MISC_TIN_OF_TREMORSTONES;
 
     case OBJ_ARMOUR:
+        if (you.get_mutation_level(MUT_NO_LOVE)
+            && is_unrandom_artefact(item, UNRAND_RATSKIN_CLOAK))
+        {
+            // some people don't like being randomly attacked by rats.
+            // weird but what can you do.
+            return true;
+        }
+
         // Tilting at windmills can be dangerous.
         return get_armour_ego_type(item) == SPARM_RAMPAGING;
 
index ae8d1a2..9e27ceb 100644 (file)
@@ -2660,7 +2660,6 @@ bool gives_ability(const item_def &item)
 
     // Unrands that grant an evokable ability.
     if (is_unrandom_artefact(item, UNRAND_THIEF)
-        || is_unrandom_artefact(item, UNRAND_RATSKIN_CLOAK)
         || is_unrandom_artefact(item, UNRAND_RCLOUDS))
     {
         return true;
index e5aa9e5..c8aa8db 100644 (file)
@@ -21,6 +21,7 @@
 #endif
 
 #include "artefact.h"
+#include "art-enum.h"
 #include "beam.h"
 #include "chardump.h"
 #include "colour.h"
@@ -525,6 +526,32 @@ static void _maybe_ru_retribution(int dam, mid_t death_source)
     }
 }
 
+static void _maybe_spawn_rats(int dam, kill_method_type death_type)
+{
+    if (dam <= 0
+        || death_type == KILLED_BY_POISON
+        || !player_equip_unrand(UNRAND_RATSKIN_CLOAK))
+    {
+        return;
+    }
+
+    // chance rises linearly with damage taken, up to 50% at half hp.
+    const int capped_dam = min(dam, you.hp_max / 2);
+    dprf("%d -> %d / %d", dam, capped_dam, you.hp_max / 2);
+    if (!x_chance_in_y(capped_dam, you.hp_max))
+        return;
+
+    monster_type mon = coinflip() ? MONS_HELL_RAT : MONS_RIVER_RAT;
+
+    mgen_data mg(mon, BEH_FRIENDLY, you.pos(), MHITYOU);
+    mg.flags |= MG_FORCE_BEH; // don't mention how much it hates you before it appears
+    if (monster *m = create_monster(mg)) {
+        m->add_ench(mon_enchant(ENCH_FAKE_ABJURATION, 3));
+        mprf("%s scurries out from under your cloak.", m->name(DESC_A).c_str());
+        check_lovelessness(*m);
+    }
+}
+
 static void _maybe_spawn_monsters(int dam, kill_method_type death_type,
                                   mid_t death_source)
 {
@@ -942,6 +969,7 @@ void ouch(int dam, kill_method_type death_type, mid_t source, const char *aux,
             _yred_mirrors_injury(dam, source);
             _maybe_ru_retribution(dam, source);
             _maybe_spawn_monsters(dam, death_type, source);
+            _maybe_spawn_rats(dam, death_type);
             _maybe_fog(dam);
             _powered_by_pain(dam);
             if (sanguine_armour_valid())
index 781125f..b687203 100644 (file)
@@ -14,7 +14,6 @@ dig ABILITY_DIG
 end_transformation ABILITY_END_TRANSFORMATION
 evoke_berserk ABILITY_EVOKE_BERSERK
 evoke_fog ABILITY_EVOKE_FOG
-evoke_ratskin ABILITY_EVOKE_RATSKIN
 evoke_thunder ABILITY_EVOKE_THUNDER
 evoke_invisibility_end ABILITY_EVOKE_INVISIBILITY_END
 evoke_invisibility ABILITY_EVOKE_INVISIBILITY
index 6df24a8..3ac33d2 100644 (file)
@@ -3427,8 +3427,6 @@ tileidx_t tileidx_ability(const ability_type ability)
         return TILEG_ABILITY_EVOKE_FLIGHT;
     case ABIL_EVOKE_FOG:
         return TILEG_ABILITY_EVOKE_FOG;
-    case ABIL_EVOKE_RATSKIN:
-        return TILEG_ABILITY_EVOKE_RATSKIN;
     case ABIL_EVOKE_THUNDER:
         return TILEG_ABILITY_EVOKE_THUNDER;