add two new Ru sacrifices
authorCorin Buchanan-Howland <corin@buchananhowland.net>
Thu, 29 Jan 2015 01:40:18 +0000 (20:40 -0500)
committerCorin Buchanan-Howland <corin@buchananhowland.net>
Thu, 29 Jan 2015 03:11:45 +0000 (22:11 -0500)
Sacrifice Skill gives you -1 to all skill aptitudes and recalculates all
your skills based on the new values. ~35 piety.

Sacrifice experience takes two experience levels and limits your max XL
to 25. ~28 piety.

Featuring terrible placeholder ability icons!

16 files changed:
crawl-ref/source/ability.cc
crawl-ref/source/dat/descript/ability.txt
crawl-ref/source/enum.h
crawl-ref/source/godabil.cc
crawl-ref/source/mutation-data.h
crawl-ref/source/player.cc
crawl-ref/source/player.h
crawl-ref/source/rltiles/dc-invocations.txt
crawl-ref/source/rltiles/gui/invocations/ru_sacrifice_experience.png [new file with mode: 0644]
crawl-ref/source/rltiles/gui/invocations/ru_sacrifice_skill.png [new file with mode: 0644]
crawl-ref/source/sacrifice-data.h
crawl-ref/source/skills.cc
crawl-ref/source/tag-version.h
crawl-ref/source/tags.cc
crawl-ref/source/tilepick.cc
crawl-ref/source/wiz-you.cc

index 7789c52..6719484 100644 (file)
@@ -438,6 +438,10 @@ static const ability_def Ability_List[] =
       0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
     { ABIL_RU_SACRIFICE_HAND, "Sacrifice a Hand",
       0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
+    { ABIL_RU_SACRIFICE_EXPERIENCE, "Sacrifice Experience",
+      0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
+    { ABIL_RU_SACRIFICE_SKILL, "Sacrifice Skill",
+      0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
     { ABIL_RU_REJECT_SACRIFICES, "Reject Sacrifices",
       0, 0, 0, 0, 0, ABFLAG_NONE },
 
@@ -1168,6 +1172,8 @@ talent get_talent(ability_type ability, bool check_confused)
     case ABIL_RU_SACRIFICE_NIMBLENESS:
     case ABIL_RU_SACRIFICE_DURABILITY:
     case ABIL_RU_SACRIFICE_HAND:
+    case ABIL_RU_SACRIFICE_EXPERIENCE:
+    case ABIL_RU_SACRIFICE_SKILL:
     case ABIL_RU_REJECT_SACRIFICES:
     case ABIL_STOP_RECALL:
         invoc = true;
@@ -3129,6 +3135,8 @@ static spret_type _do_ability(const ability_def& abil, bool fail)
     case ABIL_RU_SACRIFICE_NIMBLENESS:
     case ABIL_RU_SACRIFICE_DURABILITY:
     case ABIL_RU_SACRIFICE_HAND:
+    case ABIL_RU_SACRIFICE_EXPERIENCE:
+    case ABIL_RU_SACRIFICE_SKILL:
         fail_check();
         if (!ru_do_sacrifice(abil.ability))
             return SPRET_ABORT;
@@ -3922,6 +3930,8 @@ static int _find_ability_slot(const ability_def &abil)
       || abil.ability == ABIL_RU_SACRIFICE_NIMBLENESS
       || abil.ability == ABIL_RU_SACRIFICE_DURABILITY
       || abil.ability == ABIL_RU_SACRIFICE_HAND
+      || abil.ability == ABIL_RU_SACRIFICE_EXPERIENCE
+      || abil.ability == ABIL_RU_SACRIFICE_SKILL
       || abil.ability == ABIL_RU_REJECT_SACRIFICES)
     {
         first_slot = letter_to_index('P');
index 6c3e029..7d99b3e 100644 (file)
@@ -805,6 +805,28 @@ proportion to the value of the sacrifice, and you may gain new powers as well.
 
 Sacrifices cannot be taken back.
 %%%%
+Sacrifice Experience ability
+
+Adherents who choose to sacrifice their experiences will lose two levels
+immediately and also have the maximum level they can attain lowered by two
+levels.
+
+If you make this sacrifice, your powers granted by Ru will become stronger in
+proportion to the value of the sacrifice, and you may gain new powers as well.
+
+Sacrifices cannot be taken back.
+%%%%
+Sacrifice Skill ability
+
+Adherents who choose to sacrifice their skills will get -1 to all of their
+skill aptitudes. This will likely cause the adherent to lose ranks in skills
+they have trained.
+
+If you make this sacrifice, your powers granted by Ru will become stronger in
+proportion to the value of the sacrifice, and you may gain new powers as well.
+
+Sacrifices cannot be taken back.
+%%%%
 Reject Sacrifices ability
 
 Adherents who cannot bring themselves to make any offered sacrifice may reject
index 62c03e0..ebed2b6 100644 (file)
@@ -319,7 +319,9 @@ enum ability_type
     ABIL_RU_SACRIFICE_NIMBLENESS,
     ABIL_RU_SACRIFICE_DURABILITY,
     ABIL_RU_SACRIFICE_HAND,
-        ABIL_FINAL_SACRIFICE = ABIL_RU_SACRIFICE_HAND,
+    ABIL_RU_SACRIFICE_EXPERIENCE,
+    ABIL_RU_SACRIFICE_SKILL,
+        ABIL_FINAL_SACRIFICE = ABIL_RU_SACRIFICE_SKILL,
     ABIL_RU_REJECT_SACRIFICES,
 
     // For both Yred and Beogh
@@ -3627,6 +3629,7 @@ enum mutation_type
     MUT_SUSTAIN_ABILITIES,
 #endif
     MUT_MP_WANDS,
+    MUT_UNSKILLED,
     NUM_MUTATIONS,
 
     RANDOM_MUTATION,
index c2c5e00..a164746 100644 (file)
@@ -5924,8 +5924,10 @@ static const char* _describe_sacrifice_piety_gain(int piety_gain)
 
 static void _apply_ru_sacrifice(mutation_type sacrifice)
 {
-    perma_mutate(sacrifice, 1, "Ru sacrifice");
-    you.sacrifices[sacrifice] += 1;
+    if (sacrifice != MUT_NON_MUTATION) {
+        perma_mutate(sacrifice, 1, "Ru sacrifice");
+        you.sacrifices[sacrifice] += 1;
+    }
 }
 
 static bool _execute_sacrifice(int piety_gain, const char* message)
@@ -6022,6 +6024,32 @@ static void _extra_sacrifice_code(ability_type sac)
             }
         }
     }
+    else if (sac_def.sacrifice == ABIL_RU_SACRIFICE_EXPERIENCE)
+    {
+        lose_level();
+        lose_level();
+        you.props[MAX_XP_KEY] = you.props[MAX_XP_KEY].get_int() - 2;
+    }
+    else if (sac_def.sacrifice == ABIL_RU_SACRIFICE_SKILL)
+    {
+        uint8_t saved_skills[NUM_SKILLS];
+        for (skill_type sk = SK_FIRST_SKILL; sk < NUM_SKILLS; ++sk)
+        {
+            saved_skills[sk] = you.skills[sk];
+            check_skill_level_change(sk, false);
+        }
+
+        // Produce messages about skill increases/decreases. We
+        // restore one skill level at a time so that at most the
+        // skill being checked is at the wrong level.
+        for (skill_type sk = SK_FIRST_SKILL; sk < NUM_SKILLS; ++sk)
+        {
+            you.skills[sk] = saved_skills[sk];
+            check_skill_level_change(sk);
+        }
+
+        redraw_screen();
+    }
 }
 
 /**
index 051a903..8cc3f9f 100644 (file)
@@ -2045,4 +2045,20 @@ static const mutation_def mut_data[] =
 
   "MP-powered wands",
 },
+
+{ MUT_UNSKILLED,                        0,  3, MUTFLAG_RU, false,
+  "unskilled",
+
+  {"You are somewhat unskilled (-1 Apt).",
+    "You are unskilled (-2 Apt)",
+    "You are extremely unskilled (-3 Apt)."},
+  {"You feel less skilled.",
+    "You feel less skilled.",
+    "You feel less skilled."},
+  {"You regain all your skill.",
+    "You regain some skill.",
+    "You regain some skill."},
+
+  "a lack of skill",
+},
 };
index 4daf9d8..208183c 100644 (file)
@@ -2703,7 +2703,7 @@ static void _remove_temp_mutation()
 
 int get_exp_progress()
 {
-    if (you.experience_level >= 27)
+    if (you.experience_level >= you.props[MAX_XP_KEY].get_int())
         return 0;
 
     const int current = exp_needed(you.experience_level);
@@ -2944,7 +2944,7 @@ void level_change(bool skip_attribute_increase)
     while (you.experience < exp_needed(you.experience_level))
         lose_level();
 
-    while (you.experience_level < 27
+    while (you.experience_level < you.props[MAX_XP_KEY].get_int()
            && you.experience >= exp_needed(you.experience_level + 1))
     {
         if (!skip_attribute_increase)
@@ -2982,6 +2982,9 @@ void level_change(bool skip_attribute_increase)
 
             if (new_exp == 27)
                 mprf(MSGCH_INTRINSIC_GAIN, "You have reached level 27, the final one!");
+            else if (new_exp == you.props[MAX_XP_KEY].get_int())
+                mprf(MSGCH_INTRINSIC_GAIN, "You have reached level %d, the highest you will ever reach!",
+                        you.props[MAX_XP_KEY].get_int());
             else
             {
                 mprf(MSGCH_INTRINSIC_GAIN, "You have reached level %d!",
@@ -3478,7 +3481,7 @@ void level_change(bool skip_attribute_increase)
 
     while (you.experience >= exp_needed(you.max_level + 1))
     {
-        ASSERT(you.experience_level == 27);
+        ASSERT(you.experience_level == you.props[MAX_XP_KEY].get_int());
         ASSERT(you.max_level < 127); // marshalled as an 1-byte value
         you.max_level++;
         if (you.species == SP_FELID)
@@ -3499,19 +3502,22 @@ void level_change(bool skip_attribute_increase)
 void adjust_level(int diff, bool just_xp)
 {
     ASSERT((uint64_t)you.experience <= (uint64_t)MAX_EXP_TOTAL);
-
+    int max_exp_level = you.props[MAX_XP_KEY].get_int();
     if (you.experience_level + diff < 1)
         you.experience = 0;
-    else if (you.experience_level + diff >= 27)
-        you.experience = max(you.experience, exp_needed(27));
+    else if (you.experience_level + diff >= max_exp_level)
+        you.experience = max(you.experience,
+                exp_needed(max_exp_level));
     else
     {
-        while (diff < 0 && you.experience >= exp_needed(27))
+        while (diff < 0 && you.experience >=
+                exp_needed(max_exp_level))
         {
             // Having XP for level 53 and going back to 26 due to a single
             // card would mean your felid is not going to get any extra lives
             // in foreseable future.
-            you.experience -= exp_needed(27) - exp_needed(26);
+            you.experience -= exp_needed(max_exp_level)
+                    - exp_needed(max_exp_level - 1);
             diff++;
         }
         int old_min = exp_needed(you.experience_level);
@@ -5879,6 +5885,8 @@ void player::init()
         branch_info[it->id].branch = it->id;
         branch_info[it->id].assert_validity();
     }
+
+    you.props[MAX_XP_KEY] = 27;
 }
 
 void player::init_skills()
index 1e27001..e03281e 100644 (file)
@@ -28,6 +28,8 @@
 #define TRANSFORM_POW_KEY "transform_pow"
 #define BARBS_MOVE_KEY "moved_with_barbs_status"
 #define HORROR_PENALTY_KEY "horror_penalty"
+#define MAX_XP_KEY "max_exp_level"
+
 
 // display/messaging breakpoints for penalties from Ru's MUT_HORROR
 #define HORROR_LVL_EXTREME  3
index 2b864bb..eb25d2a 100644 (file)
@@ -66,6 +66,8 @@ ru_sacrifice_arcana ABILITY_RU_SACRIFICE_ARCANA
 ru_sacrifice_nimbleness ABILITY_RU_SACRIFICE_NIMBLENESS
 ru_sacrifice_durability ABILITY_RU_SACRIFICE_DURABILITY
 ru_sacrifice_hand ABILITY_RU_SACRIFICE_HAND
+ru_sacrifice_experience ABILITY_RU_SACRIFICE_EXPERIENCE
+ru_sacrifice_skill ABILITY_RU_SACRIFICE_SKILL
 ru_reject_sacrifices ABILITY_RU_REJECT_SACRIFICES
 sif_muna_amnesia ABILITY_SIF_MUNA_AMNESIA
 sif_muna_channel ABILITY_SIF_MUNA_CHANNEL
diff --git a/crawl-ref/source/rltiles/gui/invocations/ru_sacrifice_experience.png b/crawl-ref/source/rltiles/gui/invocations/ru_sacrifice_experience.png
new file mode 100644 (file)
index 0000000..8cf1231
Binary files /dev/null and b/crawl-ref/source/rltiles/gui/invocations/ru_sacrifice_experience.png differ
diff --git a/crawl-ref/source/rltiles/gui/invocations/ru_sacrifice_skill.png b/crawl-ref/source/rltiles/gui/invocations/ru_sacrifice_skill.png
new file mode 100644 (file)
index 0000000..b5d98ca
Binary files /dev/null and b/crawl-ref/source/rltiles/gui/invocations/ru_sacrifice_skill.png differ
index 0e3773d..516e0fd 100644 (file)
@@ -38,7 +38,7 @@ static const sacrifice_def sac_data[] =
   "sacrifice your ability to read while threatened",
   "sacrificed words",
 
-  28,
+  30,
   SK_NONE,
   nullptr,
   nullptr,
@@ -48,7 +48,7 @@ static const sacrifice_def sac_data[] =
   "sacrifice your ability to drink while threatened",
   "sacrificed drink",
 
-  28,
+  30,
   SK_NONE,
   nullptr,
   []() { return you.species != SP_MUMMY; },
@@ -128,7 +128,7 @@ static const sacrifice_def sac_data[] =
   "sacrifice your Dodging skill",
   "sacrificed dodging",
 
-  28,
+  30,
   SK_DODGING,
   nullptr,
   nullptr,
@@ -138,7 +138,7 @@ static const sacrifice_def sac_data[] =
   "sacrifice your Armour skill",
   "sacrificed armour",
 
-  28,
+  30,
   SK_ARMOUR,
   nullptr,
   []() { return you_can_wear(EQ_BODY_ARMOUR); },
@@ -153,4 +153,24 @@ static const sacrifice_def sac_data[] =
   nullptr,
   nullptr,
 },
+
+{ ABIL_RU_SACRIFICE_EXPERIENCE, MUT_NON_MUTATION,
+  "sacrifice your experiences",
+  "sacrificed experience",
+
+  28,
+  SK_NONE,
+  nullptr,
+  nullptr,
+},
+
+{ ABIL_RU_SACRIFICE_SKILL, MUT_UNSKILLED,
+  "sacrifice your skill",
+  "sacrificed skill",
+
+  35,
+  SK_NONE,
+  nullptr,
+  nullptr,
+},
 };
index aeb480b..e8604f8 100644 (file)
@@ -1575,7 +1575,7 @@ int species_apt(skill_type skill, species_type species)
         spec_skills_initialised = true;
     }
 
-    return _spec_skills[species][skill];
+    return _spec_skills[species][skill] - player_mutation_level(MUT_UNSKILLED);
 }
 
 float species_apt_factor(skill_type sk, species_type sp)
index 78e065b..adb44ac 100644 (file)
@@ -150,6 +150,7 @@ enum tag_minor_version
     TAG_MINOR_FIX_EXPLORE_MODE,    // Fix char selection screen on old versions
     TAG_MINOR_UNSTACKABLE_EVOKERS, // XP evokers no longer stack
     TAG_MINOR_NO_NEGATIVE_VULN,    // Remove negative energy vulnerability
+    TAG_MINOR_MAX_XL,              // Store max XL instead of hardcoding it
 #endif
     NUM_TAG_MINORS,
     TAG_MINOR_VERSION = NUM_TAG_MINORS - 1
index 836ac1c..f35030a 100644 (file)
@@ -3091,6 +3091,9 @@ static void tag_read_you(reader &th)
     }
 #endif
 
+    if (th.getMinorVersion() < TAG_MINOR_MAX_XL)
+        you.props["max_exp_level"] = 27;
+
     EAT_CANARY;
 
     if (!dlua.callfn("dgn_load_data", "u", &th))
index cc194ce..58dc81d 100644 (file)
@@ -5470,6 +5470,10 @@ tileidx_t tileidx_ability(const ability_type ability)
         return TILEG_ABILITY_RU_SACRIFICE_DURABILITY;
     case ABIL_RU_SACRIFICE_HAND:
         return TILEG_ABILITY_RU_SACRIFICE_HAND;
+    case ABIL_RU_SACRIFICE_EXPERIENCE:
+        return TILEG_ABILITY_RU_SACRIFICE_EXPERIENCE;
+    case ABIL_RU_SACRIFICE_SKILL:
+        return TILEG_ABILITY_RU_SACRIFICE_SKILL;
     case ABIL_RU_REJECT_SACRIFICES:
         return TILEG_ABILITY_RU_REJECT_SACRIFICES;
 
index 9cb676c..c6a11f6 100644 (file)
@@ -969,7 +969,8 @@ void wizard_set_xl()
     }
 
     const int newxl = atoi(buf);
-    if (newxl < 1 || newxl > 27 || newxl == you.experience_level)
+    if (newxl < 1 || newxl > you.props[MAX_XP_KEY].get_int()
+            || newxl == you.experience_level)
     {
         canned_msg(MSG_OK);
         return;