shadow/
shadow/data/command/
shadow/data/help/
shadow/data/religion/
shadow/data/skill/
/***************************************************************************
*  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        
*  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   
*                                                                         
*
*  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          
*  Chastain, Michael Quan, and Mitchell Tse.                              
*                                                                         
*
*  In order to use any part of this Merc Diku Mud, you must comply with   
*  both the original Diku license in 'license.doc' as well the Merc       
*  license in 'license.txt'.  In particular, you may not remove either of 
*  these copyright notices.                                               
*                                                                         
*
*  Much time and thought has gone into this software and you are          
*  benefitting.  We hope that you share your changes too.  What goes      
*  around, comes around.                                                  
*
***************************************************************************/

/***************************************************************************
*       ROM 2.4 is copyright 1993-1998 Russ Taylor                         
*
*       ROM has been brought to you by the ROM consortium                  
*
*           Russ Taylor (rtaylor@hypercube.org)                            
*
*           Gabrielle Taylor (gtaylor@hypercube.org)                       
*
*           Brian Moore (zump@rom.org)                                     
*
*       By using this code, you have agreed to follow the terms of the     
*
*       ROM license, in the file Rom24/doc/rom.license                     
*
***************************************************************************/

/**************************************************************************
***************************************************************************
***************************************************************************
***									
***
***	This file is for bard songs, and the music and play skill,	
***
***	written from scratch by me (Chaos) for the Realm of the lance	
***
***	MUD, copyright 1998.  It may be used as long as this header	
***
***	file remains intact, and my name is mentioned somewhere in the	
***
***	help file for music/play.  I would also appreciate an e-mail	
***
***	stating that you are using this and the address of your mud	
***
***	so I can come check it out!  Any comments or suggestions, or	
***
***	bugs may be e-mailed to chaos@lance.betterbox.net.  Enjoy!	
***
***									
***
***************************************************************************
***************************************************************************
**************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "include.h"

DECLARE_SONG_FUN(	song_of_huma		);
DECLARE_SONG_FUN(       song_of_soothing        );
DECLARE_SONG_FUN(       song_of_paralysis       );
DECLARE_SONG_FUN(       song_of_rage            );   

const   struct  song_type       bsong_table [MAX_SONG] =
{
/*  {
	"Song name", "Song list name", level, (void(*)(int, int, CHAR_DATA *))song_fun,
	min position, min mana, beats
    }
*/
    {
        "song of huma", "Song of Huma", 20, (void(*)(int, int, CHAR_DATA *))song_of_huma,
	POS_RESTING, 40, 25
    },

    {
        "song of soothing", "Song of Soothing", 48, (void(*)(int, int, CHAR_DATA *))song_of_soothing,
        POS_RESTING, 30, 5
    },

    {
        "song of paralysis", "Song of Paralysis", 50, (void(*)(int, int, CHAR_DATA *))song_of_paralysis,
	POS_RESTING, 50, 5
    },
       
    {
        "song of rage",      "Song of Rage", 40, (void (*)(int, int, CHAR_DATA *))song_of_rage, 
        POS_RESTING, 50, 5
    },
};

void do_songs(CHAR_DATA *ch, char *argument)
{
    char buf[MSL];
    int i;

    sprintf(buf, "{Y[%-18s %5s]{x\n\r", "Song Name", "Level");
    send_to_char(buf,ch);

    for (i = 0; i <= MAX_SONG -1; i++)
    {
	sprintf(buf, "{Y[{G%-20s {C%3d{Y]{x\n\r", bsong_table[i].listname, bsong_table[i].level);
	send_to_char(buf,ch);
    }
    return;
}


int song_lookup( const char *name )
{
    int songnum;

    for ( songnum = 0; songnum <= MAX_SKILL -1; songnum++ )
    {
	if ( bsong_table[songnum].name == NULL )
	    break;
	if ( LOWER(name[0]) == LOWER(bsong_table[songnum].name[0])
	&&   !str_cmp( name, bsong_table[songnum].name ) )
	    return songnum;
    }

    return -1;
}


void do_splay( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *instrument;
    int songnum, chance, mana, level;

    if ((chance = get_skill(ch,skill_lookup("music"))) == 0)
    {
	send_to_char("You have no clue how to play music.\n\r", ch);
	return;
    }

    if ((instrument = get_eq_char(ch, WEAR_HOLD)) == NULL)
    {
	send_to_char("You aren't carrying an instrument.\n\r", ch);
	return;
    }

    if (instrument->item_type != ITEM_INSTRUMENT)
    {
	send_to_char("You aren't carrying an instrument.\n\r", ch);
	return;
    }

    if (argument[0] == '\0')
    {
	send_to_char("Play what?\n\r", ch);
	return;
    }

    songnum = song_lookup(argument);

    if (songnum == -1)
    {
	send_to_char("That isn't a song.\n\r", ch);
	return;
    }

    if (ch->level < bsong_table[songnum].level)
    {
	send_to_char("You haven't been able to master that song yet.\n\r", ch);
	return;
    }

    if (ch->position < bsong_table[songnum].minimum_position)
    {
	send_to_char("You need to be standing up to play that song.\n\r", ch);
	return;
    }

    mana = bsong_table[songnum].min_mana;

    if (!IS_NPC(ch) && ch->mana < mana)
    {
	send_to_char("You don't have enough mana.\n\r", ch);
	return;
    }

    act("$n plays a melody on $s $p.",ch,instrument,NULL,TO_ROOM);
    act("You play a melody on your $p.",ch,instrument,NULL,TO_CHAR);

    WAIT_STATE( ch, bsong_table[songnum].beats );

    chance = chance - (20 / (1 + ch->level - bsong_table[songnum].level));

	/* average of level of player and level of instrument */
    level = (ch->level + instrument->level) / 2;

    if (number_percent() > chance)
    {
	ch->mana -= mana / 2;
	act("$n's fingers slip and the song ends abruptly.",ch,NULL,NULL,TO_ROOM);
	send_to_char("Your fingers slip and the song ends abruptly.\n\r", ch);
	check_improve(ch,skill_lookup("music"),FALSE,1);
	return;
    }
    else /* actually start playing the song */
    {
	ch->mana -= mana;
	if (IS_NPC(ch) || has_spells( ch ) )
	    (*bsong_table[songnum].song_fun) ( songnum, level, ch );
	else
	    (*bsong_table[songnum].song_fun) ( songnum, 3 * level/4, ch );
	check_improve(ch,skill_lookup("music"),TRUE,1);
    }

    return;
}

void song_of_huma( int songnum, int level, CHAR_DATA *ch )
{
    CHAR_DATA *vch;
    AFFECT_DATA af1, af2;

    af1.where = TO_AFFECTS;
    af1.type = skill_lookup("bless");
    af1.level = level;
    af1.duration = level/2;
    af1.location = APPLY_HITROLL;
    af1.modifier = level/8;
    af1.bitvector = 0;

    af2.where = TO_AFFECTS;
    af2.type = skill_lookup("armor");
    af2.level = level;
    af2.duration = level/2;
    af2.location = APPLY_AC;
    af2.modifier = -20;
    af2.bitvector = 0;

    if (!is_affected( ch, af1.type ))
    {
	act("$n glows briefly.",ch,NULL,NULL,TO_ROOM);
	send_to_char("You glow briefly.\n\r", ch);
	affect_to_char(ch,&af1);
    }

    if (!is_affected( ch, af2.type ))
    {
	act("$n is suddenly surrounded by a glowing suit of armor.",ch,NULL,NULL,TO_ROOM);
	send_to_char("You are suddenly surrounded by a glowing suit of armor.\n\r", ch);
	affect_to_char(ch,&af2);
    }

    for ( vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room )
    {
	if (ch == vch)
	    continue;

	if (!IS_NPC(vch))
	{
	    if (number_percent() <= 80 && !is_affected( vch, af1.type ))
	    {
		act("$N glows briefly.",ch,NULL,vch,TO_ROOM);
		act("$N glows briefly.",ch,NULL,vch,TO_CHAR);
		send_to_char("You glow briefly.\n\r", vch);
		affect_to_char( vch, &af1 );
	    }
	    if (number_percent() <= 80 && !is_affected( vch, af2.type ))
	    {
		act("$N is suddenly surrounded by a glowing suit of armor.",ch,NULL,vch,TO_ROOM);
		act("$N is suddenly surrounded by a glowing suit of armor.",ch,NULL,vch,TO_CHAR);
		send_to_char("You are suddenly surrounded by a glowing suit of armor.\n\r", vch);
		affect_to_char( vch, &af2 );
	    }
	}
    }

    return;
}

void song_of_soothing( int songnum, int level, CHAR_DATA *ch)
{
    CHAR_DATA *vch;
    int mlevel = 0;
    int count = 0;
    int high_level = 0;
    int chance;
    AFFECT_DATA af;
    int chance1;

    /* chances you put them to sleep */
    chance1 = number_range( 1,100 );             

    /* get sum of all mobile levels in the room */
    for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room)
    {
        if (vch->position == POS_FIGHTING)
        {
            count++;
            if (IS_NPC(vch))
              mlevel += vch->level;
            else
              mlevel += vch->level/2;
            high_level = UMAX(high_level,vch->level);
        }
    }       
                                                                   
    /* compute chance of stopping combat */
    chance = 4 * level - high_level + 2 * count;

    if (IS_IMMORTAL(ch)) /* always works */
      mlevel = 0;

    if (number_range(0, chance) >= mlevel)  /* hard to stop large fights */
    {
        for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room)
        {
            if (IS_SET(vch->imm_flags,IMM_MAGIC) ||
                                IS_SET(vch->act,ACT_UNDEAD))
              return;
        
            if ( ch == vch )
                return;

            if (IS_AFFECTED(vch,AFF_CALM) || IS_AFFECTED( vch, AFF_SLEEP)  
            ||IS_AFFECTED(vch,AFF_BERSERK)
            ||  is_affected(vch,skill_lookup("frenzy")))
              return;

            printf_to_char( ch, "A soothing wave of calm washes over %s\n\r", vch->name );
            send_to_char("A soothing wave of calm washes over you.\n\r",vch);
            act("$n feels a soothing wave of calm wash over $m.",ch,NULL,NULL,TO_ROOM);

            if (vch->fighting || vch->position == POS_FIGHTING)
              stop_fighting(vch,FALSE);
         
            if ( IS_AWAKE(vch) && chance1 <= 25 ) 
            {
                send_to_char( "You feel very sleepy ..... zzzzzz.\n\r", vch );
                act( "$n goes to sleep.", vch, NULL, NULL, TO_ROOM );
                vch->position = POS_SLEEPING;
            }  

            af.where = TO_AFFECTS;
            af.type = skill_lookup( "calm" );
            af.level = level;
            af.duration = level/4;
            af.location = APPLY_HITROLL;
            if (!IS_NPC(vch))
              af.modifier = -5;
            else
              af.modifier = -2;
            af.bitvector = AFF_CALM;
            affect_to_char(vch,&af);

            af.type = skill_lookup( "sleep" );
            af.location = APPLY_DAMROLL;
            af.modifier = -5;
            if ( chance1 <= 25 )
            {
            af.bitvector = AFF_SLEEP;
            affect_join( vch, &af );
            } 
        }
    }
}                                                                              
                                        
void song_of_paralysis( int songnum, int level, CHAR_DATA *ch)
{

     CHAR_DATA *vch;


     for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room)
     {
	if (IS_NPC(vch))
	{
	   if (vch->fighting || vch->position == POS_FIGHTING)
	      stop_fighting(vch,FALSE);
		      
           vch->position = POS_STUNNED;
           WAIT_STATE( vch, 2 * PULSE_VIOLENCE );
	   act("$n falls into a heap, stunned.", vch, NULL, NULL, TO_ROOM);
	 }
      }
}


void song_of_rage( int songnum, int level, CHAR_DATA *ch )
{
  AFFECT_DATA af1, af2;

  af1.where = TO_AFFECTS;
  af1.type = skill_lookup("bless");
  af1.level = level;
  af1.duration = level/2;
  af1.location = APPLY_HITROLL;
  af1.modifier = level/8;
  af1.bitvector = 0;

  af2.where = TO_AFFECTS;
  af2.type = skill_lookup("frenzy");
  af2.level = level;
  af2.duration = level/2;
  af2.location = APPLY_DAMROLL;
  af2.modifier = ch->level + 10/4;
  af2.bitvector = 0;

  if (is_affected(ch, af1.type))
  {
  act("$n glows briefly.",ch,NULL,NULL,TO_ROOM);
  send_to_char("You glow briefly.\n\r",ch);
  affect_to_char(ch,&af1);
  }

  if (!is_affected(ch,af2.type))
  {
    act("$n is suddenly feels much stronger and battleworthy.",ch,NULL,NULL,TO_ROOM);
    send_to_char("You feel stronger and more battle worthy.\n\r",ch);
    affect_to_char(ch,&af2);
  }

  return;
}