/*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; }