summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Feinberg <pleasingfung@gmail.com>2014-04-11 08:29:44 -0700
committerNicholas Feinberg <pleasingfung@gmail.com>2014-05-25 20:27:48 -0700
commit6f959b73ab6b07a742e45870b540a2038e405253 (patch)
treef2145783a10e15c457d8a9031eacdaee6991eed4
parentf6d44216f86f13f3ce9a7e7ee174ecb80f4248e5 (diff)
downloadcrawl-ref-6f959b73ab6b07a742e45870b540a2038e405253.tar.gz
crawl-ref-6f959b73ab6b07a742e45870b540a2038e405253.zip
Add the Majin-Bo, a new fixedart that offers power at
a terrible price. (It's not that terrible!)
-rw-r--r--crawl-ref/source/art-data.txt11
-rw-r--r--crawl-ref/source/art-func.h17
-rw-r--r--crawl-ref/source/dat/descript/unrand.txt8
-rw-r--r--crawl-ref/source/hiscores.cc7
-rw-r--r--crawl-ref/source/player.cc29
-rw-r--r--crawl-ref/source/player.h3
-rw-r--r--crawl-ref/source/rltiles/dc-player.txt1
-rw-r--r--crawl-ref/source/rltiles/item/weapon/artefact/spwpn_majin.pngbin0 -> 1549 bytes
-rw-r--r--crawl-ref/source/rltiles/player/hand1/artefact/majin.pngbin0 -> 1344 bytes
-rw-r--r--crawl-ref/source/spl-cast.cc73
-rw-r--r--crawl-ref/source/spl-util.cc17
11 files changed, 150 insertions, 16 deletions
diff --git a/crawl-ref/source/art-data.txt b/crawl-ref/source/art-data.txt
index 062f754d80..6634c9d6aa 100644
--- a/crawl-ref/source/art-data.txt
+++ b/crawl-ref/source/art-data.txt
@@ -1163,6 +1163,17 @@ INT: 3
BRAND: SPARM_ARCHMAGI
BOOL: clarity, sustab
+ENUM: MAJIN
+NAME: Majin-Bo
+OBJ: OBJ_WEAPONS/WPN_QUARTERSTAFF
+PLUS: +6/+6
+COLOUR: ETC_UNHOLY
+TILE: spwpn_majin
+TILE_EQ: majin
+MP: 6
+INT: 6
+BRAND: SPWPN_VAMPIRICISM
+
# This is the first of two amulets used to test suppression aura.
# Together, they confer every randart effect except for a few that are
# determined explicitly by checking whether a certain amulet is worn
diff --git a/crawl-ref/source/art-func.h b/crawl-ref/source/art-func.h
index c636dcfcd9..2c5a0a1fef 100644
--- a/crawl-ref/source/art-func.h
+++ b/crawl-ref/source/art-func.h
@@ -1139,3 +1139,20 @@ static void _FLAMING_DEATH_melee_effects(item_def* weapon, actor* attacker,
}
}
}
+
+///////////////////////////////////////////////////
+
+static void _MAJIN_equip(item_def *item, bool *show_msgs, bool unmeld)
+{
+ if (you.max_magic_points)
+ _equip_mpr(show_msgs, "You feel a darkness envelop your magic.");
+}
+
+static void _MAJIN_unequip(item_def *item, bool *show_msgs)
+{
+ if (you.max_magic_points)
+ {
+ _equip_mpr(show_msgs,
+ "The darkness slowly releases its grasp on your magic.");
+ }
+}
diff --git a/crawl-ref/source/dat/descript/unrand.txt b/crawl-ref/source/dat/descript/unrand.txt
index edc3a73307..97f491b96e 100644
--- a/crawl-ref/source/dat/descript/unrand.txt
+++ b/crawl-ref/source/dat/descript/unrand.txt
@@ -570,6 +570,14 @@ Carved from transparent orange crystal, this armour provides remarkable
protection for both mind and body. A skilled user can even channel psychic
energies through the crystal itself. However, it's rather heavy...
%%%%
+Majin-Bo
+
+The Majin-Bo is actually a mighty demon, tricked and trapped in this form long
+ago. To survive, she now offers tremendous arcane power at a small price: a
+tiny portion of the caster’s life essence, taken alongside the magic used every
+time its wielder casts a spell. Of course - the demon is more than happy to
+suck the life from others, as well.
+%%%%
milk chocolate
This item is a debugging aid, granting a vast array of mostly beneficial
diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc
index 85dfde43f7..ca890c2237 100644
--- a/crawl-ref/source/hiscores.cc
+++ b/crawl-ref/source/hiscores.cc
@@ -1902,6 +1902,12 @@ static bool _species_is_undead(int sp)
return sp == SP_MUMMY || sp == SP_GHOUL || sp == SP_VAMPIRE;
}
+/**
+ * Describes the cause of the player's death.
+ *
+ * @param verbosity The verbosity of the description.
+ * @return A description of the cause of death.
+ */
string scorefile_entry::death_description(death_desc_verbosity verbosity) const
{
bool needs_beam_cause_line = false;
@@ -2430,6 +2436,7 @@ string scorefile_entry::death_description(death_desc_verbosity verbosity) const
needs_damage = true;
break;
+
default:
desc += terse? "program bug" : "Nibbled to death by software bugs";
break;
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index 5d9c82cf06..2839607395 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -7175,6 +7175,35 @@ bool player::tengu_flight() const
return species == SP_TENGU && flight_mode();
}
+/**
+ * Returns the HP cost (per MP) of casting a spell.
+ *
+ * Checks to see if the player is wielding the Majin-Bo.
+ *
+ * @return The HP cost (per MP) of casting a spell.
+ **/
+int player::spell_hp_cost() const
+{
+ int cost = 0;
+
+ if (player_equip_unrand(UNRAND_MAJIN))
+ cost += 1;
+
+ return cost;
+}
+
+/**
+ * Returns true if player spellcasting is considered unholy.
+ *
+ * Checks to see if the player is wielding the Majin-Bo.
+ *
+ * @return Whether player spellcasting is an unholy act.
+ */
+bool player::spellcasting_unholy() const
+{
+ return player_equip_unrand(UNRAND_MAJIN);
+}
+
bool player::nightvision() const
{
return is_undead
diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h
index dd8c214065..2cbf7e02eb 100644
--- a/crawl-ref/source/player.h
+++ b/crawl-ref/source/player.h
@@ -444,6 +444,9 @@ public:
bool tengu_flight() const;
+ int spell_hp_cost() const;
+ bool spellcasting_unholy() const;
+
// Dealing with beholders. Implemented in behold.cc.
void add_beholder(const monster* mon, bool axe = false);
bool beheld() const;
diff --git a/crawl-ref/source/rltiles/dc-player.txt b/crawl-ref/source/rltiles/dc-player.txt
index 7324e701f0..88aa2945ca 100644
--- a/crawl-ref/source/rltiles/dc-player.txt
+++ b/crawl-ref/source/rltiles/dc-player.txt
@@ -509,6 +509,7 @@ shillelagh SHILLELAGH
dark_maul DARK_MAUL
spellbinder SPELLBINDER
firestarter FIRESTARTER
+majin MAJIN
## polearms
trident_octopus_king TRIDENT_OCTOPUS_KING
glaive_of_prune GLAIVE_OF_PRUNE
diff --git a/crawl-ref/source/rltiles/item/weapon/artefact/spwpn_majin.png b/crawl-ref/source/rltiles/item/weapon/artefact/spwpn_majin.png
new file mode 100644
index 0000000000..fe5af2d473
--- /dev/null
+++ b/crawl-ref/source/rltiles/item/weapon/artefact/spwpn_majin.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/player/hand1/artefact/majin.png b/crawl-ref/source/rltiles/player/hand1/artefact/majin.png
new file mode 100644
index 0000000000..d64b7ca602
--- /dev/null
+++ b/crawl-ref/source/rltiles/player/hand1/artefact/majin.png
Binary files differ
diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc
index dfded666a2..05297cfb22 100644
--- a/crawl-ref/source/spl-cast.cc
+++ b/crawl-ref/source/spl-cast.cc
@@ -515,6 +515,7 @@ static int _spell_enhancement(unsigned int typeflags)
enhanced -= 2;
enhanced += you.archmagi();
+ enhanced += player_equip_unrand(UNRAND_MAJIN);
#if TAG_MAJOR_VERSION == 34
if (you.species == SP_LAVA_ORC && temperature_effect(LORC_LAVA_BOOST)
@@ -607,7 +608,15 @@ void do_cast_spell_cmd(bool force)
flush_input_buffer(FLUSH_ON_FAILURE);
}
-// Returns false if spell failed, and true otherwise.
+/**
+ * Cast a spell.
+ *
+ * Handles general preconditions & costs.
+ *
+ * @param check_range If true, abort if no targets are in range. (z vs Z)
+ * @param spell The type of spell to be cast.
+ * @return Whether the spell was successfully cast.
+ **/
bool cast_a_spell(bool check_range, spell_type spell)
{
if (!_can_cast())
@@ -716,7 +725,8 @@ bool cast_a_spell(bool check_range, spell_type spell)
return false;
}
- if (!enough_mp(spell_mana(spell), true))
+ const int cost = spell_mana(spell);
+ if (!enough_mp(cost, true))
{
mpr("You don't have enough magic to cast that spell.");
crawl_state.zero_turns_taken();
@@ -774,8 +784,8 @@ bool cast_a_spell(bool check_range, spell_type spell)
const bool staff_energy = player_energy();
you.last_cast_spell = spell;
// Silently take MP before the spell.
- const int cost = spell_mana(spell);
dec_mp(cost, true);
+
const spret_type cast_result = your_spells(spell, 0, true, check_range);
if (cast_result == SPRET_ABORT)
{
@@ -840,7 +850,7 @@ static void _spellcasting_god_conduct(spell_type spell)
const int conduct_level = 10 + spell_difficulty(spell);
- if (is_unholy_spell(spell))
+ if (is_unholy_spell(spell) || you.spellcasting_unholy())
did_god_conduct(DID_UNHOLY, conduct_level);
if (is_unclean_spell(spell))
@@ -1202,12 +1212,38 @@ static double _chance_miscast_prot()
return min(1.0, miscast_prot);
}
-// Returns SPRET_SUCCESS if spell is successfully cast for purposes of
-// exercising, SPRET_FAIL otherwise, or SPRET_ABORT if the player cancelled
-// the casting.
-// Not all of these are actually real spells; invocations, decks, rods or misc.
-// effects might also land us here.
-// Others are currently unused or unimplemented.
+/**
+ * Handles damage from corrupted magic effects.
+ *
+ * Currently only from the Majin-Bo.
+ *
+ * @param spell The type of spell that was just cast.
+ **/
+static void _spellcasting_corruption(spell_type spell)
+{
+ // never kill the player (directly)
+ int hp_cost = min(you.spell_hp_cost() * spell_mana(spell), you.hp - 1);
+ const char * source = NULL;
+ if (player_equip_unrand(UNRAND_MAJIN))
+ source = "the Majin-Bo"; // for debugging
+ ouch(hp_cost, NON_MONSTER, KILLED_BY_SOMETHING, source);
+}
+
+/**
+ * Targets and fires player-cast spells & spell-like effects.
+ *
+ * Not all of these are actually real spells; invocations, decks, rods or misc.
+ * effects might also land us here.
+ * Others are currently unused or unimplemented.
+ *
+ * @param spell The type of spell being cast.
+ * @param powc Spellpower.
+ * @param allow_fail Whether spell-fail chance applies.
+ * @param check_range ...I'm not sure this actually does anything
+ * @return SPRET_SUCCESS if spell is successfully cast for purposes of
+ * exercising, SPRET_FAIL otherwise, or SPRET_ABORT if the player cancelled
+ * the casting.
+ **/
spret_type your_spells(spell_type spell, int powc,
bool allow_fail, bool check_range)
{
@@ -1385,7 +1421,13 @@ spret_type your_spells(spell_type spell, int powc,
const bool old_target = actor_at(beam.target);
- switch (_do_cast(spell, powc, spd, beam, god, potion, check_range, fail))
+ spret_type cast_result = _do_cast(spell, powc, spd, beam, god,
+ potion, check_range, fail);
+
+ if (cast_result != SPRET_ABORT && you.spell_hp_cost() && allow_fail)
+ _spellcasting_corruption(spell);
+
+ switch (cast_result)
{
case SPRET_SUCCESS:
{
@@ -1465,7 +1507,14 @@ spret_type your_spells(spell_type spell, int powc,
return SPRET_SUCCESS;
}
-// Special-cased after-effects.
+/**
+ * Handles special-cased aftereffects of spellcasting.
+ *
+ * Currently handles damage from casting Pain, since that occurs before the
+ * spellcast, whether or not it's successful, as long as it's not aborted.
+ *
+ * @param spell The type of spell that was just cast.
+ **/
static void _spell_zap_effect(spell_type spell)
{
// Casting pain costs 1 hp.
diff --git a/crawl-ref/source/spl-util.cc b/crawl-ref/source/spl-util.cc
index 3ff9ffb7fd..e812ef0533 100644
--- a/crawl-ref/source/spl-util.cc
+++ b/crawl-ref/source/spl-util.cc
@@ -1190,16 +1190,25 @@ bool spell_is_useless(spell_type spell, bool transient)
return false;
}
-// This function takes a spell, and determines what color it should be
-// highlighted with. You shouldn't have to touch this unless you want
-// to add new highlighting options.
+/**
+ * Determines what color a spell should be highlighted with.
+ *
+ * @param spell The type of spell to be colored.
+ * @param default_color Color to be used if the spell is unremarkable.
+ * @param transient If true, check if spell is temporarily useless.
+ * @param rod_spell If the spell being evoked from a rod.
+ * @return The color to highlight the spell.
+ */
int spell_highlight_by_utility(spell_type spell, int default_color,
bool transient, bool rod_spell)
{
// If your god hates the spell, that
// overrides all other concerns
- if (god_hates_spell(spell, you.religion, rod_spell))
+ if (god_hates_spell(spell, you.religion, rod_spell)
+ || is_good_god(you.religion) && you.spellcasting_unholy())
+ {
return COL_FORBIDDEN;
+ }
if (_spell_is_empowered(spell) && !rod_spell)
default_color = COL_EMPOWERED;