From e03c42d82eb8b7b5a71e4b119eeb99b235de6e1e Mon Sep 17 00:00:00 2001
From: Matthew M Ince <matthew@Y.(none)>
Date: Wed, 27 Oct 2010 18:52:32 -0400
Subject: Tukima v 1.0

---
 crawl-ref/source/dat/database/monspeak.txt |   79 ++++++++++++++++++++++++++++
 crawl-ref/source/dat/database/monspell.txt |   40 ++++++++++++++
 crawl-ref/source/dat/descript/monsters.txt |    5 ++
 crawl-ref/source/dat/descript/spells.txt   |    4 ++
 crawl-ref/source/enum.h                    |    3 +
 crawl-ref/source/main.cc                   |    3 +-
 crawl-ref/source/mgen_enum.h               |    1 +
 crawl-ref/source/mon-cast.cc               |   58 ++++++++++++++++++++-
 crawl-ref/source/mon-data.h                |   15 +++++
 crawl-ref/source/mon-place.cc              |   12 ++++-
 crawl-ref/source/mon-spll.h                |   11 ++++
 crawl-ref/source/mon-util.cc               |    1 +
 crawl-ref/source/spl-book.cc               |    2 +-
 crawl-ref/source/spl-cast.cc               |    9 +++-
 crawl-ref/source/spl-data.h                |   12 ++++
 crawl-ref/source/spl-summoning.cc          |   67 +++++++++++++++++++++++
 crawl-ref/source/spl-summoning.h           |    3 +
 17 files changed, 319 insertions(+), 6 deletions(-)

diff --git a/crawl-ref/source/dat/database/monspeak.txt b/crawl-ref/source/dat/database/monspeak.txt
index d04ac84..4a6f841 100644
--- a/crawl-ref/source/dat/database/monspeak.txt
+++ b/crawl-ref/source/dat/database/monspeak.txt
@@ -5133,6 +5133,85 @@ _Terence_rare_
 
 ## END Terence ###
 %%%%
+############ TUKIMA ### A spectral dancer
+# Cantrip messages
+Tukima_self_buff
+
+@_Tukima_self_buff_@
+%%%%
+Tukima_other_buff
+
+@_Tukima_other_buff@
+%%%%
+Tukima_debuff
+
+@_Tukima_debuff_@
+%%%%
+_Tukima_self_buff_
+
+Tukima performs a graceful pirouette.
+
+Tukima cartwheels!
+
+Tukima extends her arms.
+
+%%%%
+_Tukima_other_buff_
+
+Tukima beats her extended leg.
+
+A look of regret passes over Tukima's face.
+
+Tukima twirls.
+
+%%%%
+_Tukima_debuff_
+
+You feel light on your feet.
+
+You feel strangely compelled to dance the "Siva Afi."
+
+You feel compelled to twirl your non-existent dancing partner!
+
+Some annoying song lyrics get stuck in your head!
+
+%%%%
+Tukima
+
+@_tukima_common_@
+
+w:4
+@_tukima_rare_@
+
+%%%%
+_tukima_common_
+
+@The_monster@ exclaims, "I never get tired of watching this."
+
+@The_monster@ asks, "Have you ever felt haunted by the need to dance?"
+
+@The_monster@ explains, "If I could tell you what I felt, there would be no point in dancing it..."
+
+@The_monster@ chuckles, "Your body is so clumsy! Shall I rid you of it?"
+
+@The_monster@ calls, "Will you, won't you, will you join the dance?"
+
+@The_monster@ asks, "Would you care for a dance?"
+
+%%%%
+_tukima_rare_
+
+@The_monster@ wistfully exclaims, "I've searched so long for a dance partner..."
+
+@The_monster@ pleads, "Your soul could dance with me forever!"
+
+%%%%
+Tukima killed
+
+@The_monster@ whispers, "I'll be waiting for you..."
+
+## END Tukima ##
+%%%%
 ############ URUG ### An orc hired to kill you
 Urug
 
diff --git a/crawl-ref/source/dat/database/monspell.txt b/crawl-ref/source/dat/database/monspell.txt
index 3563d0b..0033ad5 100644
--- a/crawl-ref/source/dat/database/monspell.txt
+++ b/crawl-ref/source/dat/database/monspell.txt
@@ -145,6 +145,20 @@ Suddenly, a bright light shines from nowhere!
 
 An intense light blinds you for a moment.
 %%%%
+Tukima's Dance Party cast
+
+@The_monster@ hums a lilting melody.
+
+@The_monster@ sings a lively tune!
+
+%%%%
+unseen Tukima's Dance Party cast
+
+You hear someone hum a lilting melody!
+
+You hear someone hum a lively tune!
+
+%%%%
 #####################################################
 # Individual innate spells (breathing and spitting).
 #####################################################
@@ -257,6 +271,32 @@ You hear an invocation said in the dwarven tongue.
 You see a slight glow in a spot of thin air.
 
 Someone prays in loud words.
+
+%%%%
+Tukima cast targeted
+
+@The_monster@ looks at @target@ while chanting.
+
+@The_monster@ looks at @target@ and waves @possessive@ arms gracefully.
+
+@The_monster@ casts a spell at @target@.
+
+%%%%
+Tukima cast
+
+Tukima weaves a pattern with her spectral knives.
+
+Tukima jumps to perform a pas de chat.
+
+Tukima leaps into a pas de poisson!
+
+Tukima performs a soubresaut!
+
+%%%%
+unseen Tukima cast
+
+You hear spectral shoes clatter against the floor.
+
 %%%%
 ########################################################################
 # Individual monsters
diff --git a/crawl-ref/source/dat/descript/monsters.txt b/crawl-ref/source/dat/descript/monsters.txt
index ad86ceb..961113b 100644
--- a/crawl-ref/source/dat/descript/monsters.txt
+++ b/crawl-ref/source/dat/descript/monsters.txt
@@ -310,6 +310,11 @@ A mean-looking human fighter who likes to kill, and not much else.
 Tiamat
 
 A powerful dragon with mighty wings. Her scales seem to shimmer and change colour as you watch.
+
+%%%%
+Tukima
+
+A spectre of unearthly beauty, dancing through the air without stopping to rest or take a bow. 
 %%%%
 Urug
 
diff --git a/crawl-ref/source/dat/descript/spells.txt b/crawl-ref/source/dat/descript/spells.txt
index 38df751..98534ca 100644
--- a/crawl-ref/source/dat/descript/spells.txt
+++ b/crawl-ref/source/dat/descript/spells.txt
@@ -645,6 +645,10 @@ Throw Frost
 
 This spell throws a small bolt of frost.
 %%%%
+Tukima's Dance Party
+
+I'm afraid only weapons are invited to this party.
+%%%%
 Tukima's Dance
 
 This spell causes a weapon held in the caster's hand to dance into the air and strike the caster's enemies. It will not function on magical staves and certain wilful artefacts.
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index 819b9eb..06b8f74 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -2229,6 +2229,7 @@ enum monster_type                      // (int) menv[].type
     MONS_CHUCK,
     MONS_IRON_GIANT,
     MONS_NELLIE,
+    MONS_TUKIMA, 
     MONS_IRON_ELEMENTAL,
     MONS_EMPEROR_SCORPION,
     MONS_GHOST_MOTH,
@@ -2592,6 +2593,7 @@ enum mon_spellbook_type
     MST_PALADIN,
     MST_HOLY_DRAGON,
     MST_BOG_MUMMY,
+    MST_TUKIMA,
 
     MST_TEST_SPAWNER = 205,
     NUM_MSTYPES,
@@ -3077,6 +3079,7 @@ enum spell_type
     SPELL_STING,
     SPELL_SUBLIMATION_OF_BLOOD,
     SPELL_TUKIMAS_DANCE,
+    SPELL_TUKIMAS_DANCE_PARTY,
     SPELL_HELLFIRE,
     SPELL_SUMMON_DEMON,
     SPELL_DEMONIC_HORDE,
diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc
index adfdc79..8f88468 100644
--- a/crawl-ref/source/main.cc
+++ b/crawl-ref/source/main.cc
@@ -4238,7 +4238,8 @@ static void _compile_time_asserts()
     COMPILE_CHECK(SK_EVOCATIONS == 38           , c2);
     COMPILE_CHECK(SP_VAMPIRE == 30              , c3);
 #if TAG_MAJOR_VERSION == 31
-    COMPILE_CHECK(NUM_SPELLS == 225             , c6);
+    COMPILE_CHECK(NUM_SPELLS == 226 , c6);
+    //COMPILE_CHECK(NUM_SPELLS == 225             , c6);
 #else
     COMPILE_CHECK(NUM_SPELLS == 224             , c6);
 #endif
diff --git a/crawl-ref/source/mgen_enum.h b/crawl-ref/source/mgen_enum.h
index ffc0a6f..b8c6f6d 100644
--- a/crawl-ref/source/mgen_enum.h
+++ b/crawl-ref/source/mgen_enum.h
@@ -63,6 +63,7 @@ enum band_type
     BAND_ALLIGATOR,
     BAND_ELEPHANT,
     BAND_DEEP_DWARF,
+    BAND_TUKIMA, 
     NUM_BANDS                   // always last
 };
 
diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc
index 448ff02..09b8def 100644
--- a/crawl-ref/source/mon-cast.cc
+++ b/crawl-ref/source/mon-cast.cc
@@ -956,6 +956,7 @@ bool setup_mons_cast(monster* mons, bolt &pbolt, spell_type spell_cast,
     // fire_tracer, or beam.
     switch (spell_cast)
     {
+    case SPELL_TUKIMAS_DANCE_PARTY:
     case SPELL_STICKS_TO_SNAKES:
     case SPELL_SUMMON_SMALL_MAMMALS:
     case SPELL_VAMPIRIC_DRAINING:
@@ -1570,6 +1571,17 @@ bool handle_mon_spell(monster* mons, bolt &beem)
             mons->lose_energy(EUT_SPELL);
             return (true);
         }
+	// Try to animate weapons: if none are animated, pretend we didn't cast it.
+	if (spell_cast == SPELL_TUKIMAS_DANCE_PARTY)
+	  {
+	    //friendly monsters cannot cast tukima's dance party for now.
+	    if (mons->friendly()) {
+	      return false;
+	    }
+	    if (!cast_tukimas_dance_party(mons, 100, GOD_NO_GOD ,true)) {
+	      return false;
+	    }
+	  }
 
         // Try to animate dead: if nothing rises, pretend we didn't cast it.
         if (spell_cast == SPELL_ANIMATE_DEAD)
@@ -2648,7 +2660,13 @@ void mons_cast(monster* mons, bolt &pbolt, spell_type spell_cast,
                           god));
         }
         return;
-
+	//Tukima's dance NOT handled here.
+	//Instead, handle above in handle_mon_spell
+	//so nothing happens if no weapons animated.
+     case SPELL_TUKIMAS_DANCE_PARTY:
+//         if (cast_tukimas_dance_party(mons, 100, GOD_NO_GOD, SAME_ATTITUDE(mons)))
+         mpr("Haunting music fills the air, and weapons rise to join the dance!");
+         return;
     case SPELL_ANIMATE_DEAD:
         animate_dead(mons, 5 + random2(5), SAME_ATTITUDE(mons),
                      mons->foe, mons, "", god);
@@ -2975,6 +2993,44 @@ void mons_cast(monster* mons, bolt &pbolt, spell_type spell_cast,
         const msg_channel_type channel = (friendly) ? MSGCH_FRIEND_ENCHANT
                                                     : MSGCH_MONSTER_ENCHANT;
 
+	if (mons->type == MONS_TUKIMA) 
+	  {
+	    std::string dance_compulsion = "";
+	    bool has_mon_foe = !invalid_monster_index(mons->foe);
+	    if (buff_only || crawl_state.game_is_arena() && !has_mon_foe
+                || friendly && !has_mon_foe || coinflip())
+	      {
+		dance_compulsion = getSpeakString("Tukima_self_buff");
+                if (!dance_compulsion.empty())
+                {
+                    dance_compulsion = replace_all(dance_compulsion, "@The_monster@",
+                                           mons->name(DESC_CAP_THE));
+                    mpr(dance_compulsion.c_str(), channel);
+                }
+	      }
+	    else if (!friendly && !has_mon_foe)
+	      {
+                mons_cast_noise(mons, pbolt, spell_cast);
+		dance_compulsion = getSpeakString("Tukima_debuff");
+                if (!dance_compulsion.empty())
+                {
+                    mpr(dance_compulsion.c_str());
+                }
+	      }
+	    else 
+	      {
+		dance_compulsion =getSpeakString("Tukima_other_buff");
+                const monster* foe      = mons->get_foe()->as_monster();
+		
+                if (!dance_compulsion.empty())
+                {
+                    dance_compulsion = replace_all(dance_compulsion, "@The_monster@",
+                                           foe->name(DESC_CAP_THE));
+                    mpr(dance_compulsion.c_str(), MSGCH_MONSTER_ENCHANT);
+                }
+	      }
+	  }
+	  
         if (mons->type == MONS_GASTRONOK)
         {
             bool has_mon_foe = !invalid_monster_index(mons->foe);
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index 422ebe8..1c7c9d1 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -5590,6 +5590,21 @@ static monsterentry mondata[] = {
     MONUSE_WEAPONS_ARMOUR, MONEAT_NOTHING, SIZE_LARGE
 },
 
+
+
+{
+    MONS_TUKIMA, 'p', LIGHTMAGENTA, "Tukima",
+    M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS
+      | M_SPEAKS | M_DEFLECT_MISSILES,
+    MR_NO_FLAGS,
+      600, 10, MONS_PHANTOM , MONS_PHANTOM, MH_UNDEAD, -6,
+    { {AT_HIT, AF_PLAIN, 30}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
+    { 18, 0, 0, 140 },
+    7, 25, MST_TUKIMA, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT,
+    I_HIGH, HT_LAND, FL_NONE, 10, DEFAULT_ENERGY,
+    MONUSE_NOTHING, MONEAT_NOTHING, SIZE_MEDIUM
+},
+
 {
     MONS_MARA, 'R', LIGHTMAGENTA, "Mara",
     M_SPELLCASTER | M_SEE_INVIS | M_SPEAKS | M_UNIQUE,
diff --git a/crawl-ref/source/mon-place.cc b/crawl-ref/source/mon-place.cc
index 7f0e437..fe509d2 100644
--- a/crawl-ref/source/mon-place.cc
+++ b/crawl-ref/source/mon-place.cc
@@ -2281,7 +2281,11 @@ static band_type _choose_band(int mon_type, int power, int &band_size,
             band_size = 1 + random2(3);
         }
         break;
-
+    case MONS_TUKIMA:
+        natural_leader=true;
+        band = BAND_TUKIMA;
+        band_size = 1 + random_range(1,3);
+        break;
     case MONS_PANDEMONIUM_DEMON:
         natural_leader = true;
         band = BAND_PANDEMONIUM_DEMON;
@@ -2745,7 +2749,11 @@ static monster_type _band_member(band_type band, int power)
                  (temp_rand == 1) ? MONS_DEEP_ELF_SORCERER      // 1 in 16
                                   : MONS_DEEP_ELF_DEATH_MAGE);  // 1 in 16
         break;
-
+    case BAND_TUKIMA:
+        mon_type=MONS_DANCING_WEAPON;
+        if (one_chance_in(4)) 
+	  mon_type = MONS_PHANTOM;
+        break;
     case BAND_HELL_KNIGHTS:
         mon_type = MONS_HELL_KNIGHT;
         if (one_chance_in(4))
diff --git a/crawl-ref/source/mon-spll.h b/crawl-ref/source/mon-spll.h
index 0a6e667..c420db6 100644
--- a/crawl-ref/source/mon-spll.h
+++ b/crawl-ref/source/mon-spll.h
@@ -1207,6 +1207,17 @@
        SPELL_NO_SPELL
       }
     },
+     
+    {  MST_TUKIMA,
+      {
+       SPELL_TUKIMAS_DANCE_PARTY,
+       SPELL_SWIFTNESS,
+       SPELL_CORONA,
+       SPELL_BLINK,
+       SPELL_CANTRIP,
+       SPELL_CANTRIP
+      }
+    },
 
     {  MST_KIRKE,
       {
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index b193084..4633523 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -3211,6 +3211,7 @@ const char *mons_pronoun(monster_type mon_type, pronoun_type variant,
     {
         switch (mon_type)
         {
+	case MONS_TUKIMA:
         case MONS_JESSICA:
         case MONS_PSYCHE:
         case MONS_JOSEPHINE:
diff --git a/crawl-ref/source/spl-book.cc b/crawl-ref/source/spl-book.cc
index bd10936..32d0281 100644
--- a/crawl-ref/source/spl-book.cc
+++ b/crawl-ref/source/spl-book.cc
@@ -393,7 +393,7 @@ static spell_type spellbook_template_array[][SPELLBOOK_SIZE] =
     {SPELL_SURE_BLADE,
      SPELL_TUKIMAS_VORPAL_BLADE,
      SPELL_TUKIMAS_DANCE,
-     SPELL_NO_SPELL,
+     SPELL_TUKIMAS_DANCE_PARTY,
      SPELL_NO_SPELL,
      SPELL_NO_SPELL,
      SPELL_NO_SPELL,
diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc
index 9e6b699..082d2c1 100644
--- a/crawl-ref/source/spl-cast.cc
+++ b/crawl-ref/source/spl-cast.cc
@@ -1579,7 +1579,14 @@ static spret_type _do_cast(spell_type spell, int powc,
     case SPELL_SUMMON_DRAGON:
         cast_summon_dragon(powc, god);
         break;
-
+    case SPELL_TUKIMAS_DANCE_PARTY:
+      if (cast_tukimas_dance_party(&you, powc, god)) {
+	mpr("Haunting music fills the air, and weapons rise to join the dance!");
+      } else {
+	mpr("Strange music fills the air, but nothing else happens.");
+      }
+	
+      break;
     case SPELL_TUKIMAS_DANCE:
         // Temporarily turns a wielded weapon into a dancing weapon.
         cast_tukimas_dance(powc, god);
diff --git a/crawl-ref/source/spl-data.h b/crawl-ref/source/spl-data.h
index 06a4002..70902ee 100644
--- a/crawl-ref/source/spl-data.h
+++ b/crawl-ref/source/spl-data.h
@@ -1071,6 +1071,18 @@ struct spell_desc
      true
 },
 
+{  SPELL_TUKIMAS_DANCE_PARTY, "Tukima's Dance Party", 
+    SPTYP_ENCHANTMENT,
+    SPFLAG_NONE,
+    6,
+    200,
+    -1,-1,
+    0,
+    NULL,
+    false,
+    true
+},
+
 {
     SPELL_TUKIMAS_DANCE, "Tukima's Dance",
      SPTYP_ENCHANTMENT,
diff --git a/crawl-ref/source/spl-summoning.cc b/crawl-ref/source/spl-summoning.cc
index 489b3ed..7fafe45 100644
--- a/crawl-ref/source/spl-summoning.cc
+++ b/crawl-ref/source/spl-summoning.cc
@@ -780,6 +780,73 @@ bool summon_holy_warrior(int pow, god_type god, int spell,
                                       !force_hostile, quiet);
 }
 
+
+static bool _can_weapon_dance(item_def* wpn) {
+  if (!wpn
+      || wpn->base_type != OBJ_WEAPONS
+      || is_range_weapon(*wpn)
+      || is_special_unrandom_artefact(*wpn))
+    {
+      return false;
+    }
+  return true;
+}
+
+//mass tukima's dance
+//arguments should include an actor, like animate dead. 
+bool cast_tukimas_dance_party(actor *caster, int pow, god_type god, bool force_hostile) 
+{
+  bool some_weapon_was_animated = false;
+  const int dur = std::min(2 + (random2(pow) / 5), 6);
+
+  radius_iterator ri(caster->pos(), 6, C_SQUARE,
+		     caster->get_los_no_trans());
+  //iterate over all weapons in view 
+  for (; ri; ++ri) {
+    for (stack_iterator si(*ri) ; si ; ++ si) {
+      if (si->base_type == OBJ_WEAPONS) {
+	if (!_can_weapon_dance(&(*si)) ){ 
+	 	mprf("%s flop%s limply for a second.",
+	     si->name(DESC_CAP_THE).c_str(),
+	     si->quantity > 1 ? "" : "s");
+		continue;
+	}
+	//attempt to animate weapon
+	item_def wpn = *si;
+
+
+        // Cursed weapons become hostile.
+        const bool friendly = (!force_hostile && !wpn.cursed());
+	int mons=-1;
+	mgen_data mg( MONS_DANCING_WEAPON,
+		      friendly ? BEH_FRIENDLY : BEH_HOSTILE, // BEH_HOSTILE
+		      force_hostile ? 0 : caster, // Tukima
+		      dur,     // 0
+		      SPELL_TUKIMAS_DANCE,      // summon type MON_SUMM_ANIMATE
+		      *ri, // ... not sure what the coords should be
+		      MHITYOU, // MHITYOU
+		      0, // mgen_flag_type - might be MG_PLAYER_MADE or MG_FORCE_PLACE
+		      god); // if you animate the weapon, your god gets mad if it poisons/drains stuff
+	mg.props[TUKIMA_WEAPON] = wpn;
+	mons = create_monster(mg);
+	int success = (mons != -1);
+	some_weapon_was_animated |= success;
+
+	//remove weapon from ground if animated
+	if (success) {
+	  destroy_item(si->index());
+	}
+      }
+    }
+  }
+
+  // Right now, nothing is animated...
+  return some_weapon_was_animated;
+
+  //TODO: add awesome disco lighting and rename the spell "Tukima's rave"
+}
+
+
 // This function seems to have very little regard for encapsulation.
 bool cast_tukimas_dance(int pow, god_type god, bool force_hostile)
 {
diff --git a/crawl-ref/source/spl-summoning.h b/crawl-ref/source/spl-summoning.h
index 7f06ef9..6f3f6ac 100644
--- a/crawl-ref/source/spl-summoning.h
+++ b/crawl-ref/source/spl-summoning.h
@@ -33,6 +33,9 @@ bool summon_berserker(int pow, god_type god = GOD_NO_GOD, int spell = 0,
 bool summon_holy_warrior(int pow, god_type god = GOD_NO_GOD, int spell = 0,
                          bool force_hostile = false, bool permanent = false,
                          bool quiet = false);
+
+bool cast_tukimas_dance_party(actor *caster, int pow, god_type god=GOD_NO_GOD, bool force_hostile = false);
+
 bool cast_tukimas_dance(int pow, god_type god = GOD_NO_GOD,
                         bool force_hostile = false);
 bool cast_conjure_ball_lightning(int pow, god_type god = GOD_NO_GOD);
-- 
1.6.3.3

