/*Bard Special Stuff -- Work in Progress
Josh - 2/1/02*/
#include "include.h"
#include "interp.h"
#include "bard.h"
#include "recycle.h"
char *target_name;
bool isSung;
void do_play_instrument (CHAR_DATA * ch, char *argument)
{
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
OBJ_DATA *obj;
void *vo;
int mana;
int sn;
int target;
OBJ_DATA *instrument;
isSung = FALSE;
/*
* Switched NPC's can play songs, but others can't.
*/
if (IS_NPC (ch) && ch->desc == NULL)
return;
if (ch->class != MAX_CLASS && !(IS_IMMORTAL(ch)))
{
send_to_char("You couldn't play an instrument if your life depended on it.\n\r", ch);
return;
}
target_name = one_argument (argument, arg1);
one_argument (target_name, arg2);
if (arg1[0] == '\0')
{
send_to_char ("Play what where?\n\r", ch);
return;
}
if ((instrument = get_eq_char (ch, WEAR_HOLD)) == NULL)
{
send_to_char ("You hold nothing in your hand.\n\r", ch);
return;
}
if (instrument->item_type != ITEM_INSTRUMENT)
{
send_to_char ("You aren't holding an instrument!\n\r", ch);
return;
}
if ((sn = find_spell (ch, arg1)) < 1
|| skill_table[sn].slot != 999
|| skill_table[sn].spell_fun == spell_null || (!IS_NPC (ch)
&& (ch->level < skill_table[sn].skill_level[ch->class]
|| ch->pcdata->learned[sn] == 0)))
{
send_to_char ("You don't know any songs of that name.\n\r", ch);
return;
}
if (ch->position < skill_table[sn].minimum_position)
{
send_to_char ("You can't concentrate enough.\n\r", ch);
return;
}
if (ch->level + 2 == skill_table[sn].skill_level[ch->class])
mana = 50;
else
mana = UMAX (skill_table[sn].min_mana,
100 / (2 + ch->level -
skill_table[sn].skill_level[ch->class]));
/*
* Locate targets.
*/
victim = NULL;
obj = NULL;
vo = NULL;
target = TARGET_NONE;
switch (skill_table[sn].target)
{
default:
bug ("Do_play: bad target for sn %d.", sn);
return;
case TAR_IGNORE:
break;
case TAR_CHAR_OFFENSIVE:
if (arg2[0] == '\0')
{
if ((victim = ch->fighting) == NULL)
{
send_to_char ("Play the song to whom?\n\r", ch);
return;
}
}
else
{
if ((victim = get_char_room (ch, target_name)) == NULL)
{
send_to_char ("They aren't here.\n\r", ch);
return;
}
}
/*
if ( ch == victim )
{
send_to_char( "You can't do that to yourself.\n\r", ch );
return;
}
*/
if (!IS_NPC (ch))
{
if (is_safe (ch, victim) && victim != ch)
{
send_to_char ("Not on that target.\n\r", ch);
return;
}
check_killer (ch, victim);
}
if (IS_AFFECTED (ch, AFF_CHARM) && ch->master == victim)
{
send_to_char ("You can't do that on your own follower.\n\r",
ch);
return;
}
vo = (void *) victim;
target = TARGET_CHAR;
break;
case TAR_CHAR_DEFENSIVE:
if (arg2[0] == '\0')
{
victim = ch;
}
else
{
if ((victim = get_char_room (ch, target_name)) == NULL)
{
send_to_char ("They aren't here.\n\r", ch);
return;
}
}
vo = (void *) victim;
target = TARGET_CHAR;
break;
case TAR_CHAR_SELF:
if (arg2[0] != '\0' && !is_name (target_name, ch->name))
{
send_to_char ("You cannot play this song to another.\n\r",
ch);
return;
}
vo = (void *) ch;
target = TARGET_CHAR;
break;
case TAR_OBJ_INV:
if (arg2[0] == '\0')
{
send_to_char ("What should the song be bound to?\n\r", ch);
return;
}
if ((obj = get_obj_carry (ch, target_name, ch)) == NULL)
{
send_to_char ("You are not carrying that.\n\r", ch);
return;
}
vo = (void *) obj;
target = TARGET_OBJ;
break;
case TAR_OBJ_CHAR_OFF:
if (arg2[0] == '\0')
{
if ((victim = ch->fighting) == NULL)
{
send_to_char ("Play the song to whom or what?\n\r", ch);
return;
}
target = TARGET_CHAR;
}
else if ((victim = get_char_room (ch, target_name)) != NULL)
{
target = TARGET_CHAR;
}
if (target == TARGET_CHAR)
{ /* check the sanity of the attack */
if (is_safe_spell (ch, victim, FALSE) && victim != ch)
{
send_to_char ("Not on that target.\n\r", ch);
return;
}
if (IS_AFFECTED (ch, AFF_CHARM) && ch->master == victim)
{
send_to_char
("You can't do that on your own follower.\n\r", ch);
return;
}
if (!IS_NPC (ch))
check_killer (ch, victim);
vo = (void *) victim;
}
else if ((obj = get_obj_here (ch, target_name)) != NULL)
{
vo = (void *) obj;
target = TARGET_OBJ;
}
else
{
send_to_char ("You don't see that here.\n\r", ch);
return;
}
break;
case TAR_OBJ_CHAR_DEF:
if (arg2[0] == '\0')
{
vo = (void *) ch;
target = TARGET_CHAR;
}
else if ((victim = get_char_room (ch, target_name)) != NULL)
{
vo = (void *) victim;
target = TARGET_CHAR;
}
else if ((obj = get_obj_carry (ch, target_name, ch)) != NULL)
{
vo = (void *) obj;
target = TARGET_OBJ;
}
else
{
send_to_char ("You don't see that here.\n\r", ch);
return;
}
break;
}
if (!IS_NPC (ch) && ch->mana < mana)
{
send_to_char ("You don't have enough mana.\n\r", ch);
return;
}
WAIT_STATE (ch, skill_table[sn].beats);
if (number_percent () > get_skill (ch, sn))
{
send_to_char ("You fumbled a note.\n\r", ch);
check_improve (ch, sn, FALSE, 1);
ch->mana -= mana / 2;
}
else
{
ch->mana -= mana;
if (IS_NPC (ch) || class_table[ch->class].fMana)
/* class has spells */
(*skill_table[sn].spell_fun) (sn, ch->level, ch, vo, target);
else
(*skill_table[sn].spell_fun) (sn, 3 * ch->level / 4, ch, vo, target);
check_improve (ch, sn, TRUE, 1);
}
if ((skill_table[sn].target == TAR_CHAR_OFFENSIVE
|| (skill_table[sn].target == TAR_OBJ_CHAR_OFF
&& target == TARGET_CHAR)) && victim != ch
&& victim->master != ch)
{
CHAR_DATA *vch;
CHAR_DATA *vch_next;
for (vch = ch->in_room->people; vch; vch = vch_next)
{
vch_next = vch->next_in_room;
if (victim == vch && victim->fighting == NULL)
{
check_killer (victim, ch);
multi_hit (victim, ch, TYPE_UNDEFINED);
break;
}
}
}
return;
}
void do_sing (CHAR_DATA * ch, char *argument)
{
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
OBJ_DATA *obj;
void *vo;
int mana;
int sn;
int target;
isSung = TRUE;
/*
* Switched NPC's can sing songs, but others can't.
*/
if (IS_NPC (ch) && ch->desc == NULL)
return;
if (ch->class != MAX_CLASS && !(IS_IMMORTAL(ch)))
{
send_to_char("You couldn't sing if your life depended on it.\n\r", ch);
return;
}
target_name = one_argument (argument, arg1);
one_argument (target_name, arg2);
if (arg1[0] == '\0')
{
send_to_char ("Play what where?\n\r", ch);
return;
}
if ((sn = find_spell (ch, arg1)) < 1
|| skill_table[sn].slot != 999
|| skill_table[sn].spell_fun == spell_null || (!IS_NPC (ch)
&& (ch->level < skill_table[sn].skill_level[ch->class]
|| ch->pcdata->learned[sn] == 0)))
{
send_to_char ("You don't know any songs of that name.\n\r", ch);
return;
}
if (ch->position < skill_table[sn].minimum_position)
{
send_to_char ("You can't concentrate enough.\n\r", ch);
return;
}
if (ch->level + 2 == skill_table[sn].skill_level[ch->class])
mana = 50;
else
mana = UMAX (skill_table[sn].min_mana,
100 / (2 + ch->level -
skill_table[sn].skill_level[ch->class]));
/*
* Locate targets.
*/
victim = NULL;
obj = NULL;
vo = NULL;
target = TARGET_NONE;
switch (skill_table[sn].target)
{
default:
bug ("Do_play: bad target for sn %d.", sn);
return;
case TAR_IGNORE:
break;
case TAR_CHAR_OFFENSIVE:
if (arg2[0] == '\0')
{
if ((victim = ch->fighting) == NULL)
{
send_to_char ("Sing the song to whom?\n\r", ch);
return;
}
}
else
{
if ((victim = get_char_room (ch, target_name)) == NULL)
{
send_to_char ("They aren't here.\n\r", ch);
return;
}
}
/*
if ( ch == victim )
{
send_to_char( "You can't do that to yourself.\n\r", ch );
return;
}
*/
if (!IS_NPC (ch))
{
if (is_safe (ch, victim) && victim != ch)
{
send_to_char ("Not on that target.\n\r", ch);
return;
}
check_killer (ch, victim);
}
if (IS_AFFECTED (ch, AFF_CHARM) && ch->master == victim)
{
send_to_char ("You can't do that on your own follower.\n\r",
ch);
return;
}
vo = (void *) victim;
target = TARGET_CHAR;
break;
case TAR_CHAR_DEFENSIVE:
if (arg2[0] == '\0')
{
victim = ch;
}
else
{
if ((victim = get_char_room (ch, target_name)) == NULL)
{
send_to_char ("They aren't here.\n\r", ch);
return;
}
}
vo = (void *) victim;
target = TARGET_CHAR;
break;
case TAR_CHAR_SELF:
if (arg2[0] != '\0' && !is_name (target_name, ch->name))
{
send_to_char ("You cannot sing this song to another.\n\r",
ch);
return;
}
vo = (void *) ch;
target = TARGET_CHAR;
break;
case TAR_OBJ_INV:
if (arg2[0] == '\0')
{
send_to_char ("What should the song be bound to?\n\r", ch);
return;
}
if ((obj = get_obj_carry (ch, target_name, ch)) == NULL)
{
send_to_char ("You are not carrying that.\n\r", ch);
return;
}
vo = (void *) obj;
target = TARGET_OBJ;
break;
case TAR_OBJ_CHAR_OFF:
if (arg2[0] == '\0')
{
if ((victim = ch->fighting) == NULL)
{
send_to_char ("Sing the song to whom or what?\n\r", ch);
return;
}
target = TARGET_CHAR;
}
else if ((victim = get_char_room (ch, target_name)) != NULL)
{
target = TARGET_CHAR;
}
if (target == TARGET_CHAR)
{ /* check the sanity of the attack */
if (is_safe_spell (ch, victim, FALSE) && victim != ch)
{
send_to_char ("Not on that target.\n\r", ch);
return;
}
if (IS_AFFECTED (ch, AFF_CHARM) && ch->master == victim)
{
send_to_char
("You can't do that on your own follower.\n\r", ch);
return;
}
if (!IS_NPC (ch))
check_killer (ch, victim);
vo = (void *) victim;
}
else if ((obj = get_obj_here (ch, target_name)) != NULL)
{
vo = (void *) obj;
target = TARGET_OBJ;
}
else
{
send_to_char ("You don't see that here.\n\r", ch);
return;
}
break;
case TAR_OBJ_CHAR_DEF:
if (arg2[0] == '\0')
{
vo = (void *) ch;
target = TARGET_CHAR;
}
else if ((victim = get_char_room (ch, target_name)) != NULL)
{
vo = (void *) victim;
target = TARGET_CHAR;
}
else if ((obj = get_obj_carry (ch, target_name, ch)) != NULL)
{
vo = (void *) obj;
target = TARGET_OBJ;
}
else
{
send_to_char ("You don't see that here.\n\r", ch);
return;
}
break;
}
if (!IS_NPC (ch) && ch->mana < mana)
{
send_to_char ("You don't have enough mana.\n\r", ch);
return;
}
WAIT_STATE (ch, skill_table[sn].beats);
if (number_percent () > get_skill (ch, sn))
{
send_to_char ("You sang off key.\n\r", ch);
check_improve (ch, sn, FALSE, 1);
ch->mana -= mana / 2;
}
else
{
ch->mana -= mana;
if (IS_NPC (ch) || class_table[ch->class].fMana)
/* class has spells */
(*skill_table[sn].spell_fun) (sn, ch->level, ch, vo, target);
else
(*skill_table[sn].spell_fun) (sn, 3 * ch->level / 4, ch, vo, target);
check_improve (ch, sn, TRUE, 1);
}
if ((skill_table[sn].target == TAR_CHAR_OFFENSIVE
|| (skill_table[sn].target == TAR_OBJ_CHAR_OFF
&& target == TARGET_CHAR)) && victim != ch
&& victim->master != ch)
{
CHAR_DATA *vch;
CHAR_DATA *vch_next;
for (vch = ch->in_room->people; vch; vch = vch_next)
{
vch_next = vch->next_in_room;
if (victim == vch && victim->fighting == NULL)
{
check_killer (victim, ch);
multi_hit (victim, ch, TYPE_UNDEFINED);
break;
}
}
}
return;
}
/*Song Lookup*/
void do_songs (CHAR_DATA * ch, char *argument)
{
BUFFER *buffer;
char arg[MAX_INPUT_LENGTH];
char spell_list[LEVEL_HERO + 1][MAX_STRING_LENGTH];
char spell_columns[LEVEL_HERO + 1];
int sn, level, min_lev = 1, max_lev = LEVEL_HERO, mana;
bool fAll = FALSE, found = FALSE;
char buf[MAX_STRING_LENGTH];
if (IS_NPC (ch))
return;
if (argument[0] != '\0')
{
fAll = TRUE;
if (str_prefix (argument, "all"))
{
argument = one_argument (argument, arg);
if (!is_number (arg))
{
send_to_char ("Arguments must be numerical or all.\n\r", ch);
return;
}
max_lev = atoi (arg);
if (max_lev < 1 || max_lev > LEVEL_HERO)
{
sprintf (buf, "Levels must be between 1 and %d.\n\r",
LEVEL_HERO);
send_to_char (buf, ch);
return;
}
if (argument[0] != '\0')
{
argument = one_argument (argument, arg);
if (!is_number (arg))
{
send_to_char ("Arguments must be numerical or all.\n\r",
ch);
return;
}
min_lev = max_lev;
max_lev = atoi (arg);
if (max_lev < 1 || max_lev > LEVEL_HERO)
{
sprintf (buf,
"Levels must be between 1 and %d.\n\r",
LEVEL_HERO);
send_to_char (buf, ch);
return;
}
if (min_lev > max_lev)
{
send_to_char ("That would be silly.\n\r", ch);
return;
}
}
}
}
/* initialize data */
for (level = 0; level < LEVEL_HERO + 1; level++)
{
spell_columns[level] = 0;
spell_list[level][0] = '\0';
}
for (sn = 0; sn < MAX_SKILL; sn++)
{
if (skill_table[sn].name == NULL)
break;
if ((level = skill_table[sn].skill_level[ch->class]) < LEVEL_HERO + 1
&& (fAll || level <= ch->level)
&& level >= min_lev && level <= max_lev
&& skill_table[sn].spell_fun != spell_null
&& skill_table[sn].slot == 999
&& ch->pcdata->learned[sn] > 0)
{
found = TRUE;
level = skill_table[sn].skill_level[ch->class];
if (ch->level < level)
sprintf (buf, "%-18s n/a ", skill_table[sn].name);
else
{
mana = UMAX (skill_table[sn].min_mana,
100 / (2 + ch->level - level));
sprintf (buf, "%-18s %3d mana ", skill_table[sn].name,
mana);
}
if (spell_list[level][0] == '\0')
sprintf (spell_list[level], "\n\rLevel %2d: %s", level, buf);
else
{ /* append */
if (++spell_columns[level] % 2 == 0)
strcat (spell_list[level], "\n\r ");
strcat (spell_list[level], buf);
}
}
}
/* return results */
if (!found)
{
send_to_char ("No songs found.\n\r", ch);
return;
}
buffer = new_buf ();
for (level = 0; level < LEVEL_HERO + 1; level++)
if (spell_list[level][0] != '\0')
add_buf (buffer, spell_list[level]);
add_buf (buffer, "\n\r");
page_to_char (buf_string (buffer), ch);
free_buf (buffer);
}
/*Start
Songs*/
void song_test(int sn, int level, CHAR_DATA * ch, void *vo,
int target)
{
OBJ_DATA *instrument;
instrument = get_eq_char (ch, WEAR_HOLD);
if(isSung)
{
act("You sing the test song.", ch, instrument, NULL, TO_CHAR);
act("$n sings the test song.", ch, instrument, NULL, TO_ROOM);
}
else
{
act("You play the test song on $p.", ch, instrument, NULL, TO_CHAR);
act("$n plays the test song on $p.", ch, instrument, NULL, TO_ROOM);
}
return;
}