/***************************************************************************
* 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-1996 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@pacinfo.com) *
* Gabrielle Taylor (gtaylor@pacinfo.com) *
* Brian Moore (rom@rom.efn.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file Tartarus/doc/rom.license *
***************************************************************************/
/***************************************************************************
* Tartarus code is copyright (C) 1997-1998 by Daniel Graham *
* In using this code you agree to comply with the Tartarus license *
* found in the file /Tartarus/doc/tartarus.doc *
***************************************************************************/
#include "include.h"
/* command procedures needed */
DECLARE_DO_FUN(do_groups );
DECLARE_DO_FUN(do_help );
DECLARE_DO_FUN(do_say );
int is_spec_skill args((int sn));
int is_mob_spec args((int sn));
bool is_specced args((CHAR_DATA *ch,int spec));
char *target_name;
int weapon_num_lookup args((const char *name));
char * weapon_name_lookup args((int type));
bool checkScrollsAcumen args( (CHAR_DATA *ch) );
/* used to get new skills */
void do_gain(CHAR_DATA *ch, char *argument)
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *trainer;
if (IS_NPC(ch))
return;
/* find a trainer */
for ( trainer = ch->in_room->people;
trainer != NULL;
trainer = trainer->next_in_room)
if (IS_NPC(trainer) && (IS_SET(trainer->act,ACT_GAIN)
|| IS_SET(trainer->act,ACT_TRAIN)) )
break;
if (trainer == NULL || !can_see(ch,trainer))
{
send_to_char("You can't do that here.\n\r",ch);
return;
}
one_argument(argument,arg);
if (arg[0] == '\0')
{
do_say(trainer,"Use gain convert to convert 10 practices into 1 train.");
do_say(trainer,"Or use gain revert to revert 1 train into 10 practices.");
return;
}
if (!str_prefix(arg,"convert"))
{
if (ch->practice < 10)
{
act("$N tells you 'You are not yet ready.'",
ch,NULL,trainer,TO_CHAR);
return;
}
act("$N helps you apply your practice to training",
ch,NULL,trainer,TO_CHAR);
ch->practice -= 10;
ch->train +=1 ;
return;
}
/* 'gain revert' converts one train into 10 pracs */
if (!str_prefix(arg,"revert"))
{
if (ch->train < 1)
{
act("$N tells you 'You do not have the training to apply to your skill practices yet.'",
ch,NULL,trainer,TO_CHAR);
return;
}
act("$N helps you apply your training to skills practices.",
ch,NULL,trainer,TO_CHAR);
ch->practice += 10;
ch->train -= 1 ;
return;
}
act("$N tells you 'I do not understand...'",ch,NULL,trainer,TO_CHAR);
return;
}
/* RT spells and skills show the players spells (or skills) */
void do_spells(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(class_table[ch->class].ctype!=CLASS_CASTER)
{
send_to_char("Your class knows no spells.\n\r",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
&& level >= min_lev && level <= max_lev
&& skill_table[sn].spell_fun != spell_null
&& ch->pcdata->learned[sn] > 0
&& (skill_table[sn].ctype==CMD_SPELL || skill_table[sn].ctype==CMD_BOTH))
{
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));
switch (get_curr_stat(ch,STAT_INT)) {
case 25: mana = 43 * mana / 50; break;
case 24: mana = 22 * mana / 25; break;
case 23: mana = 45 * mana / 50; break;
case 22: mana = 23 * mana / 25; break;
case 21: mana = 47 * mana / 50; break;
case 20: mana = 24 * mana / 25; break;
case 19: mana = 49 * mana / 50; break;
}
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 spells 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);
}
void do_skills(CHAR_DATA *ch, char *argument)
{
BUFFER *buffer;
char arg[MAX_INPUT_LENGTH];
char skill_list[LEVEL_HERO + 1][MAX_STRING_LENGTH];
char skill_columns[LEVEL_HERO + 1];
int sn, level, min_lev = 1, max_lev = LEVEL_HERO;
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++)
{
skill_columns[level] = 0;
skill_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
&& ch->pcdata->learned[sn] > 0)*/
if ((level = skill_table[sn].skill_level[ch->class]) < LEVEL_HERO + 1
&& level >= min_lev && level <= max_lev
&& skill_table[sn].spell_fun == spell_null
&& 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
sprintf(buf,"%-18s %3d%% ",skill_table[sn].name,
ch->pcdata->learned[sn]);
if (skill_list[level][0] == '\0')
sprintf(skill_list[level],"\n\rLevel %2d: %s",level,buf);
else /* append */
{
if ( ++skill_columns[level] % 2 == 0)
strcat(skill_list[level],"\n\r ");
strcat(skill_list[level],buf);
}
}
}
/* return results */
if (!found)
{
send_to_char("No skills found.\n\r",ch);
return;
}
buffer = new_buf();
for (level = 0; level < LEVEL_HERO + 1; level++)
if (skill_list[level][0] != '\0')
add_buf(buffer,skill_list[level]);
add_buf(buffer,"\n\r");
page_to_char(buf_string(buffer),ch);
free_buf(buffer);
}
/* shows skills, groups and costs (only if not bought) */
void list_group_costs(CHAR_DATA *ch)
{
return;
}
void list_group_chosen(CHAR_DATA *ch)
{
if (IS_NPC(ch))
return;
return;
}
int exp_per_level(CHAR_DATA *ch)
{
int epl;
if (IS_NPC(ch))
return 1500;
epl = pc_race_table[ch->race].xpadd + class_table[ch->class].xpadd + 1500;
epl += (ch->level -1) * epl * .08;
return epl;
}
/* this procedure handles the input parsing for the skill generator */
bool parse_gen_groups(CHAR_DATA *ch,char *argument)
{
char arg[MAX_INPUT_LENGTH];
char buf[100];
int gn,sn,i;
if (argument[0] == '\0')
return FALSE;
argument = one_argument(argument,arg);
if (!str_prefix(arg,"help"))
{
if (argument[0] == '\0')
{
do_help(ch,"group help");
return TRUE;
}
do_help(ch,argument);
return TRUE;
}
if (!str_prefix(arg,"add"))
{
if (argument[0] == '\0')
{
send_to_char("You must provide a skill name.\n\r",ch);
return TRUE;
}
gn = group_lookup(argument);
if (gn != -1)
{
if (ch->gen_data->group_chosen[gn]
|| ch->pcdata->group_known[gn])
{
send_to_char("You already know that group!\n\r",ch);
return TRUE;
}
if (group_table[gn].rating[ch->class] < 1)
{
send_to_char("That group is not available.\n\r",ch);
return TRUE;
}
sprintf(buf,"%s group added\n\r",group_table[gn].name);
send_to_char(buf,ch);
ch->gen_data->group_chosen[gn] = TRUE;
ch->gen_data->points_chosen += group_table[gn].rating[ch->class];
gn_add(ch,gn);
return TRUE;
}
sn = skill_lookup(argument);
if (sn != -1)
{
if (ch->gen_data->skill_chosen[sn]
|| ch->pcdata->learned[sn] > 0)
{
send_to_char("You already know that skill!\n\r",ch);
return TRUE;
}
if (skill_table[sn].rating[ch->class] < 1
|| skill_table[sn].spell_fun != spell_null)
{
send_to_char("That skill is not available.\n\r",ch);
return TRUE;
}
sprintf(buf, "%s skill added\n\r",skill_table[sn].name);
send_to_char(buf,ch);
ch->gen_data->skill_chosen[sn] = TRUE;
ch->gen_data->points_chosen += skill_table[sn].rating[ch->class];
ch->pcdata->learned[sn] = 1;
return TRUE;
}
send_to_char("No skills or groups by that name...\n\r",ch);
return TRUE;
}
if (!strcmp(arg,"drop"))
{
if (argument[0] == '\0')
{
send_to_char("You must provide a skill to drop.\n\r",ch);
return TRUE;
}
gn = group_lookup(argument);
if (gn != -1 && ch->gen_data->group_chosen[gn])
{
send_to_char("Group dropped.\n\r",ch);
ch->gen_data->group_chosen[gn] = FALSE;
ch->gen_data->points_chosen -= group_table[gn].rating[ch->class];
gn_remove(ch,gn);
for (i = 0; i < MAX_GROUP; i++)
{
if (ch->gen_data->group_chosen[gn])
gn_add(ch,gn);
}
return TRUE;
}
sn = skill_lookup(argument);
if (sn != -1 && ch->gen_data->skill_chosen[sn])
{
send_to_char("Skill dropped.\n\r",ch);
ch->gen_data->skill_chosen[sn] = FALSE;
ch->gen_data->points_chosen -= skill_table[sn].rating[ch->class];
ch->pcdata->learned[sn] = 0;
return TRUE;
}
send_to_char("You haven't bought any such skill or group.\n\r",ch);
return TRUE;
}
if (!str_prefix(arg,"premise"))
{
do_help(ch,"premise");
return TRUE;
}
if (!str_prefix(arg,"list"))
{
list_group_costs(ch);
return TRUE;
}
if (!str_prefix(arg,"learned"))
{
list_group_chosen(ch);
return TRUE;
}
if (!str_prefix(arg,"info"))
{
do_groups(ch,argument);
return TRUE;
}
return FALSE;
}
/* shows all groups, or the sub-members of a group */
void do_groups(CHAR_DATA *ch, char *argument)
{
if (IS_NPC(ch))
return;
return;
}
/* checks for skill improvement */
void check_improve( CHAR_DATA *ch, int sn, bool success, int multiplier )
{
int chance;
char buf[MSL];
if (IS_NPC(ch))
return;
if (ch->level < skill_table[sn].skill_level[ch->class]
|| skill_table[sn].rating[ch->class] == 0
|| ch->pcdata->learned[sn] == 0
|| ch->pcdata->learned[sn] == 100)
return;
/* check to see if the character has a chance to learn */
chance = 15 * int_app[get_curr_stat(ch,STAT_INT)].learn;
chance /= (multiplier * skill_table[sn].rating[ch->class] * 4);
if (ch->pcdata->newbie == TRUE && (sn == gsn_assassinate || sn == gsn_impale || sn == gsn_cleave || sn == skill_lookup("power word kill")))
{
return;
}
if (IS_SET(ch->act,PLR_MORON))
chance /= 6;
if (checkScrollsAcumen(ch))
chance *= 6;
if (number_range(1,500) > chance)
return;
/* now that the character has a CHANCE to learn, see if they really have */
if (success)
{
chance = URANGE(30,100 - ch->pcdata->learned[sn], 95);
if (number_percent() < chance)
{
ch->pcdata->learned[sn]++;
if (get_skill(ch,sn) == 100)
sprintf(buf,"{GYou have perfected %s!{x\n\r",skill_table[sn].name);
else
sprintf(buf,"{YYou have become better at %s!{x\n\r",skill_table[sn].name);
send_to_char(buf,ch);
}
}
else
{
chance = URANGE(25,ch->pcdata->learned[sn]/2,60);
if (number_percent() < chance)
{
ch->pcdata->learned[sn] += number_range(1,3);
ch->pcdata->learned[sn] = UMIN(ch->pcdata->learned[sn],100);
if (get_skill(ch,sn) == 100)
sprintf(buf,"{GYou learn from your mistakes, and manage to perfect %s!{x\n\r",skill_table[sn].name);
else
sprintf(buf,"{YYou learn from your mistakes, and your %s skill improves!{x\n\r",skill_table[sn].name);
send_to_char(buf,ch);
}
}
}
/* returns a group index number given the name */
int group_lookup( const char *name )
{
int gn;
for ( gn = 0; gn < MAX_GROUP; gn++ )
{
if ( group_table[gn].name == NULL )
break;
if ( LOWER(name[0]) == LOWER(group_table[gn].name[0])
&& !str_prefix( name, group_table[gn].name ) )
return gn;
}
return -1;
}
/* recursively adds a group given its number -- uses group_add */
void gn_add( CHAR_DATA *ch, int gn)
{
int i;
ch->pcdata->group_known[gn] = TRUE;
for ( i = 0; i < MAX_IN_GROUP; i++)
{
if (group_table[gn].spells[i] == NULL)
break;
group_add(ch,group_table[gn].spells[i],FALSE);
}
}
/* recusively removes a group given its number -- uses group_remove */
void gn_remove( CHAR_DATA *ch, int gn)
{
int i;
ch->pcdata->group_known[gn] = FALSE;
for ( i = 0; i < MAX_IN_GROUP; i ++)
{
if (group_table[gn].spells[i] == NULL)
break;
group_remove(ch,group_table[gn].spells[i]);
}
}
/* use for processing a skill or group for addition */
void group_add( CHAR_DATA *ch, const char *name, bool deduct)
{
int sn,gn;
if (IS_NPC(ch)) /* NPCs do not have skills */
return;
sn = skill_lookup(name);
if (sn != -1)
{
if (ch->pcdata->learned[sn] == 0) /* i.e. not known */
{
ch->pcdata->learned[sn] = 1;
}
return;
}
/* now check groups */
gn = group_lookup(name);
if (gn != -1)
{
if (ch->pcdata->group_known[gn] == FALSE)
{
ch->pcdata->group_known[gn] = TRUE;
}
gn_add(ch,gn); /* make sure all skills in the group are known */
}
}
/* used for processing a skill or group for deletion -- no points back! */
void group_remove(CHAR_DATA *ch, const char *name)
{
int sn, gn;
sn = skill_lookup(name);
if (sn != -1)
{
ch->pcdata->learned[sn] = 0;
return;
}
/* now check groups */
gn = group_lookup(name);
if (gn != -1 && ch->pcdata->group_known[gn] == TRUE)
{
ch->pcdata->group_known[gn] = FALSE;
gn_remove(ch,gn); /* be sure to call gn_add on all remaining groups */
}
}
void do_specialize(CHAR_DATA *ch,char *argument)
{
char arg[MAX_INPUT_LENGTH];
char buf[MAX_STRING_LENGTH];
int i;
bool already = FALSE;
bool anyspecs = FALSE;
if (IS_NPC(ch))
return;
if (IS_SET(ch->act,PLR_BETRAYER)) {
send_to_char("You don't feel ready to specialize.\n\r",ch);
return;
}
if (ch->pcdata->special == 0)
{
send_to_char("You have no specializations available.\n\r",ch);
return;
}
one_argument(argument,arg);
if (arg[0] == '\0')
{
send_to_char("You can currently specialize in: ",ch);
for (i=1;i<=MAX_WEAPON;i++) {
already = FALSE;
already = is_specced(ch,i);
if (already == FALSE) {
anyspecs = TRUE;
send_to_char(weapon_name_lookup(i),ch);
send_to_char(" ",ch);
}
}
if (anyspecs)
send_to_char("\n\r",ch);
else
send_to_char("nothing.\n\r",ch);
return;
}
if (weapon_num_lookup(arg) > 0) {
for (i=0;i<=MAX_SPECS;i++) {
if (get_skill(ch,skill_lookup(arg)) < 80) {
send_to_char("You do not feel knowledgable enough in that weapon to specialize in it.\n\r",ch);
return;
}
if (!ch->pcdata->warrior_specs[i]) {
ch->pcdata->warrior_specs[i] = weapon_num_lookup(arg);
already = TRUE;
break;
} else {
if ((ch->pcdata->warrior_specs[i] == weapon_num_lookup(arg)) ||
(ch->pcdata->warrior_specs[i] == WEAPON_STAFF && weapon_num_lookup(arg) == WEAPON_SPEAR) ||
(ch->pcdata->warrior_specs[i] == WEAPON_SPEAR && weapon_num_lookup(arg) == WEAPON_STAFF) ||
(ch->pcdata->warrior_specs[i] == WEAPON_WHIP && weapon_num_lookup(arg) == WEAPON_FLAIL) ||
(ch->pcdata->warrior_specs[i] == WEAPON_FLAIL && weapon_num_lookup(arg) == WEAPON_WHIP)) {
send_to_char("You are already specialized in that.\n\r",ch);
return;
}
}
}
if (!already) {
send_to_char("You cannot specialize anymore!\n\r",ch);
return;
}
sprintf(buf,"ws %s",weapon_name_lookup(weapon_num_lookup(arg)));
group_add(ch,buf,FALSE);
send_to_char("You are now specialized in ",ch);
send_to_char(weapon_name_lookup(weapon_num_lookup(arg)),ch);
send_to_char(".\n\r",ch);
ch->pcdata->special--;
} else {
send_to_char("You can't specialize in that.\n\r",ch);
return;
}
return;
}
int is_spec_skill(int sn) {
int i,gn,gns,gsn;
char buf[MAX_STRING_LENGTH];
for (i=1;i<=MAX_WEAPON;i++) {
sprintf(buf,"ws %s",weapon_name_lookup(i));
gn = group_lookup(buf);
for (gns = 0; gns <= MAX_SPEC_SKILLS; gns++)
{
gsn = skill_lookup(group_table[gn].spells[gns]);
if (gsn == sn) {
return i;
}
}
}
return -1;
}
int is_mob_spec(int sn) {
int i,gns,gsn;
for (i=GROUP_SWORD;i<=GROUP_POLEARM;i++) {
for (gns = 0; gns <=4; gns++)
{
if(!group_table[i].spells[gns])
break;
gsn = skill_lookup(group_table[i].spells[gns]);
if (gsn == sn)
return i;
}
}
return -1;
}
bool is_specced(CHAR_DATA *ch,int spec) {
int j;
if (IS_IMMORTAL(ch))
return TRUE;
if(IS_NPC(ch))
{
if(spec==GROUP_SWORD && IS_SET(ch->extended_flags,OFF_SWORD_SPEC))
return TRUE;
if(spec==GROUP_AXE && IS_SET(ch->extended_flags,OFF_AXE_SPEC))
return TRUE;
if(spec==GROUP_HTH && IS_SET(ch->extended_flags,OFF_HTH_SPEC))
return TRUE;
if(spec==GROUP_DAGGER && IS_SET(ch->extended_flags,OFF_DAGGER_SPEC))
return TRUE;
if(spec==GROUP_SPEAR && IS_SET(ch->extended_flags,OFF_SPEAR_SPEC))
return TRUE;
if(spec==GROUP_MACE && IS_SET(ch->extended_flags,OFF_MACE_SPEC))
return TRUE;
if(spec==GROUP_WHIP && IS_SET(ch->extended_flags,OFF_WHIP_SPEC))
return TRUE;
if(spec==GROUP_POLEARM && IS_SET(ch->extended_flags,OFF_POLEARM_SPEC))
return TRUE;
return FALSE;
}
for (j=0;j<=MAX_SPECS;j++) {
if ((ch->pcdata->warrior_specs[j] == spec) ||
(ch->pcdata->warrior_specs[j] == WEAPON_STAFF && spec == WEAPON_SPEAR) ||
(ch->pcdata->warrior_specs[j] == WEAPON_SPEAR && spec == WEAPON_STAFF) ||
(ch->pcdata->warrior_specs[j] == WEAPON_WHIP && spec == WEAPON_FLAIL) ||
(ch->pcdata->warrior_specs[j] == WEAPON_FLAIL && spec == WEAPON_WHIP)) {
return TRUE;
}
}
return FALSE;
}
void do_gag( CHAR_DATA *ch, char *argument)
{
char arg[MIL], buf[MSL];
CHAR_DATA *victim;
AFFECT_DATA af;
int percent, chance;
one_argument(argument,arg);
if ((chance = get_skill(ch,gsn_gag)) == 0 )
{
send_to_char("You do not know where to start.\n\r",ch);
return;
}
if (arg[0] == '\0')
{
send_to_char("Gag who?\n\r",ch);
return;
}
if (ch->fighting != NULL)
{
send_to_char("You can't do that while fighting.\n\r",ch);
return;
}
if ((victim = get_char_room(ch,arg)) == NULL)
{
send_to_char("They aren't here.\n\r",ch);
return;
}
if (victim == ch)
{
send_to_char("Kinky.\n\r", ch);
return;
}
if (is_safe(ch,victim))
return;
if(victim->position > POS_SLEEPING)
return send_to_char("But they are still awake!\n\r",ch);
chance += get_curr_stat(ch,STAT_DEX) - get_curr_stat(victim,STAT_DEX);
chance += URANGE(-10, (ch->level - victim->level), 10);
WAIT_STATE(ch,skill_table[gsn_gag].beats);
percent = number_percent();
if (percent > chance || percent > 90)
{
sprintf(buf, "Help! %s just tried to gag me!",PERS(ch,victim));
do_myell(victim,buf);
check_improve(ch,gsn_gag,FALSE,1);
damage(ch,victim,1,gsn_gag,DAM_NONE,TRUE);
act("You tie a gag around $N's mouth, but it falls off.",ch,NULL,victim,TO_CHAR);
act("$n ties a gag around $N's mouth, but it falls off.",ch,NULL,victim,TO_NOTVICT);
}
else if (percent < 3 * chance /4)
{
if (!IS_AWAKE(victim))
do_wake(victim,"");
if (IS_NPC(victim) && IS_AWAKE(victim))
multi_hit(victim,ch,TYPE_UNDEFINED);
init_affect(&af);
af.type = gsn_gag;
af.aftype = AFT_SKILL;
af.level = ch->level;
af.duration = number_range(0,1);
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = 0;
affect_to_char(victim,&af);
check_improve(ch,gsn_gag,TRUE,1);
act("You deftly slide a gag into $N's mouth.",ch,NULL,victim,TO_CHAR);
act("$n slides a gag into $N's mouth.",ch,NULL,victim,TO_NOTVICT);
}
}
void do_call( CHAR_DATA *ch, char *argument )
{
char buf[MAX_STRING_LENGTH];
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
OBJ_DATA *obj;
void *vo;
int mana;
int sn;
int target;
if ( IS_NPC(ch) && ch->desc == NULL)
return;
target_name = one_argument( argument, arg1 );
one_argument( target_name, arg2 );
if ( arg1[0] == '\0' )
return send_to_char( "Call which what where?\n\r", ch );
if ((sn = find_spell(ch,arg1)) < 1
|| (!IS_NPC(ch) && get_skill(ch,sn) < 5)
|| (!IS_NPC(ch) && ch->pcdata->learned[sn] == 0))
return send_to_char( "You don't know any powers of that name.\n\r", ch );
if ( ch->position < skill_table[sn].minimum_position && get_trust(ch)<MAX_LEVEL-1)
return send_to_char( "You can't concentrate enough.\n\r", ch );
if(skill_table[sn].ctype!=CMD_POWER && !IS_IMMORTAL(ch))
return send_to_char("You can't call that.\n\r",ch);
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] ) );
switch (get_curr_stat(ch,STAT_INT)) {
case 25: mana = 43 * mana / 50; break;
case 24: mana = 22 * mana / 25; break;
case 23: mana = 45 * mana / 50; break;
case 22: mana = 23 * mana / 25; break;
case 21: mana = 47 * mana / 50; break;
case 20: mana = 24 * mana / 25; break;
case 19: mana = 49 * mana / 50; break;
}
{
}
/*
* Locate targets.
*/
victim = NULL;
obj = NULL;
vo = NULL;
target = TARGET_NONE;
switch ( skill_table[sn].target )
{
default:
bug( "Do_cast: bad target for sn %d.", sn );
return;
case TAR_IGNORE:
break;
case TAR_CHAR_OFFENSIVE:
if ( arg2[0] == '\0' )
{
if ( ( victim = ch->fighting ) == NULL )
return send_to_char( "Call the power on whom?\n\r", ch );
}
else
{
if ( ( victim = get_char_room( ch, target_name ) ) == NULL )
return send_to_char( "They aren't here.\n\r", ch );
}
if ( !IS_NPC(ch) )
check_killer(ch,victim);
if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
return send_to_char( "You can't do that on your own master.\n\r", ch );
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 )
return send_to_char( "They aren't here.\n\r", ch );
}
vo = (void *) victim;
target = TARGET_CHAR;
break;
case TAR_CHAR_SELF:
if ( arg2[0] != '\0' && !is_name( target_name, ch->name ) )
return send_to_char( "You cannot call this power on another.\n\r", ch );
vo = (void *) ch;
target = TARGET_CHAR;
break;
case TAR_OBJ_INV:
if ( arg2[0] == '\0' )
return send_to_char( "What should the power be called upon?\n\r", ch );
if ( ( obj = get_obj_carry( ch, target_name, ch ) ) == NULL )
return send_to_char( "You are not carrying that.\n\r", ch );
vo = (void *) obj;
target = TARGET_OBJ;
break;
case TAR_OBJ_CHAR_OFF:
if (arg2[0] == '\0')
{
if ((victim = ch->fighting) == NULL)
return send_to_char("Call the power on who or what?\n\r",ch);
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_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
return send_to_char( "You can't do that on your own follower.\n\r", ch );
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
return send_to_char("You don't see that here.\n\r",ch);
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
return send_to_char("You don't see that here.\n\r",ch);
break;
}
if ( !IS_NPC(ch) && ch->mana < mana )
return send_to_char( "You don't have enough mana.\n\r", ch );
WAIT_STATE( ch, skill_table[sn].beats );
if ( !IS_NPC(ch) && (number_percent( ) > get_skill(ch,sn)))
{
send_to_char( "You lost your concentration.\n\r", ch );
check_improve(ch,sn,FALSE,1);
ch->mana -= mana / 2;
}
else
{
ch->mana -= mana;
if (skill_table[sn].target == TAR_CHAR_OFFENSIVE
&& is_safe(ch,victim))
return;
if (skill_table[sn].target == TAR_CHAR_OFFENSIVE)
{
if (!IS_NPC(ch) && !IS_NPC(victim)
&& (ch->fighting == NULL || victim->fighting == NULL))
{
switch(number_range(0,2))
{
case (0):
case (1):
sprintf(buf,"Die, %s you sorcerous dog!",PERS(ch,victim));
break;
case (2):
sprintf(buf,"Help! %s is casting a spell on me!",PERS(ch,victim));
}
if (victim != ch && !IS_NPC(ch))
do_myell(victim,buf);
}
}
(*skill_table[sn].spell_fun) ( sn, ch->level, 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;
}
bool checkScrollsAcumen(CHAR_DATA *ch)
{
OBJ_DATA *scrolls;
scrolls = get_eq_char(ch, WEAR_HOLD);
if (scrolls == NULL)
return FALSE;
if (scrolls->pIndexData->vnum != 1231)
return FALSE;
return TRUE;
}
void do_plant_explosive( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
char arg1[MIL], arg2[MIL], *target;
if (get_skill(ch,skill_lookup("plant explosive")) <= 0)
return send_to_char("You don't know how to plant explosives.\n\r",ch);
if (is_affected(ch,skill_lookup("plant explosive")))
return send_to_char("You have not yet crafted another explosive to plant.\n\r",ch);
target = one_argument(argument,arg1);
one_argument(target,arg2);
if (arg1[0] == '\0')
return send_to_char("You must specify a target.\n\r",ch);
if ((victim = get_char_room(ch,arg1)) == NULL)
return send_to_char("They aren't here.\n\r",ch);
if (victim == ch)
return send_to_char("You wouldn't do that to yourself.\n\r",ch);
if (is_safe(ch,victim))
return;
if (IS_NPC(victim))
return send_to_char("They are too wary for you to plant an explosive on.\n\r",ch);
if (isNewbie(victim) || victim->ghost != 0)
return send_to_char("You cannot plant explosives on those who cannot defend themselves.\n\r",ch);
if (arg2[0] == '\0')
return send_to_char("You must specify a timer for the explosive.\n\r",ch);
if (atoi(arg2) <= 0)
return send_to_char("You can't set a timer that is less than at least an hour!\n\r",ch);
int bombDuration = atoi(arg2);
int chance = number_percent();
AFFECT_DATA af;
init_affect(&af);
af.duration = bombDuration;
af.where = TO_AFFECTS;
af.aftype = AFT_POWER;
af.level = 60;
af.type = skill_lookup("plant explosive");
af.affect_list_msg = str_dup("prevents planting of explosives");
if (chance <= 80)
{
char buf[MSL];
OBJ_DATA *explosive = create_object(get_obj_index(OBJ_VNUM_THIEF_PLANT_EXPLOSIVE),55);
explosive->timer = bombDuration;
explosive->level = bombDuration;
char *wordOne = NULL, *wordTwo = NULL, *wordThree = NULL;
switch(number_range(1,29))
{
case 1: wordOne = str_dup("a black"); break;
case 2: wordOne = str_dup("a ruby-laden"); break;
case 3: wordOne = str_dup("a jade-encrusted");break;
case 4: wordOne = str_dup("an ornate");break;
case 5: wordOne = str_dup("an exquisite");break;
case 6: wordOne = str_dup("a gleaming white");break;
case 7: wordOne = str_dup("a glinting");break;
case 8: wordOne = str_dup("a heavy");break;
case 9: wordOne = str_dup("an ancient");break;
case 10: wordOne = str_dup("a dusty");break;
case 11: wordOne = str_dup("an intricately-decorated");break;
case 12: wordOne = str_dup("a large");break;
case 13: wordOne = str_dup("an enormous");break;
case 14: wordOne = str_dup("a dull");break;
case 15: wordOne = str_dup("a red");break;
case 16: wordOne = str_dup("a blue-hued");break;
case 17: wordOne = str_dup("a chromatic");break;
case 18: wordOne = str_dup("a shining");break;
case 19: wordOne = str_dup("a blackened");break;
case 20: wordOne = str_dup("a slightly charred");break;
case 21: wordOne = str_dup("a finely-crafted");break;
case 22: wordOne = str_dup("a grey-tinted");break;
case 23: wordOne = str_dup("a glimmering");break;
case 24: wordOne = str_dup("a long-forgotten");break;
case 25: wordOne = str_dup("a polished");break;
case 26: wordOne = str_dup("a battered");break;
case 27: wordOne = str_dup("a fiery");break;
case 28: wordOne = str_dup("an ice-encrusted");break;
case 29: wordOne = str_dup("a pulsing");break;
}
switch(number_range(1,23))
{
case 1: wordTwo = str_dup("steel");break;
case 2: wordTwo = str_dup("iron");break;
case 3: wordTwo = str_dup("wooden");break;
case 4: wordTwo = str_dup("mithril");break;
case 5: wordTwo = str_dup("glass");break;
case 6: wordTwo = str_dup("stone");break;
case 7: wordTwo = str_dup("silver");break;
case 8: wordTwo = str_dup("gold");break;
case 9: wordTwo = str_dup("adamantite");break;
case 10: wordTwo = str_dup("brass");break;
case 11: wordTwo = str_dup("bronze");break;
case 12: wordTwo = str_dup("crystal");break;
case 13: wordTwo = str_dup("ivory");break;
case 14: wordTwo = str_dup("diamond");break;
case 15: wordTwo = str_dup("golden");break;
case 16: wordTwo = str_dup("wood");break;
case 17: wordTwo = str_dup("onyx");break;
case 18: wordTwo = str_dup("bone");break;
case 19: wordTwo = str_dup("metallic");break;
case 20: wordTwo = str_dup("metal");break;
case 22: wordTwo = str_dup("obsidian");break;
case 23: wordTwo = str_dup("dragonscale");break;
}
switch(number_range(1,37))
{
case 1: wordThree = str_dup("sword");break;
case 2: wordThree = str_dup("axe");break;
case 3: wordThree = str_dup("whip");break;
case 4: wordThree = str_dup("flail");break;
case 5: wordThree = str_dup("pike");break;
case 6: wordThree = str_dup("spear");break;
case 7: wordThree = str_dup("polearm");break;
case 8: wordThree = str_dup("blade");break;
case 9: wordThree = str_dup("dagger");break;
case 10: wordThree = str_dup("skewer");break;
case 11: wordThree = str_dup("double-bladed axe");break;
case 12: wordThree = str_dup("cleaver");break;
case 13: wordThree = str_dup("bastard sword");break;
case 14: wordThree = str_dup("great axe");break;
case 15: wordThree = str_dup("poleaxe");break;
case 16: wordThree = str_dup("halberd");break;
case 17: wordThree = str_dup("mace");break;
case 18: wordThree = str_dup("hammer");break;
case 19: wordThree = str_dup("double-bladed sword");break;
case 20: wordThree = str_dup("breastplate");break;
case 21: wordThree = str_dup("helmet");break;
case 22: wordThree = str_dup("helm");break;
case 23: wordThree = str_dup("shortsword");break;
case 24: wordThree = str_dup("longsword");break;
case 25: wordThree = str_dup("morning-star");break;
case 26: wordThree = str_dup("skull cap");break;
case 27: wordThree = str_dup("shortspear");break;
case 28: wordThree = str_dup("long spear");break;
case 29: wordThree = str_dup("chest harness");break;
case 30: wordThree = str_dup("chest-protector");break;
case 31: wordThree = str_dup("torso");break;
case 32: wordThree = str_dup("cap");break;
case 33: wordThree = str_dup("full helm");break;
case 34: wordThree = str_dup("dirk");break;
case 35: wordThree = str_dup("hand-axe");break;
case 36: wordThree = str_dup("large axe");break;
case 37: wordThree = str_dup("claymore");break;
}
sprintf(buf,"%s %s %s", wordOne, wordTwo, wordThree);
char bufname[MSL];
sprintf(bufname, "%s %s", wordTwo, wordThree);
explosive->name = str_dup(bufname);
explosive->short_descr = str_dup(buf);
sprintf(buf, "%s %s %s is lying here.", wordOne, wordTwo, wordThree);
explosive->description = str_dup(buf);
explosive->owner = str_dup(ch->original_name);
obj_to_char(explosive,victim);
affect_to_char(ch,&af);
sprintf(buf,"You have successfully planted an explosive among %s's belongings!\n\r",victim->name);
return send_to_char(buf,ch);
}
else if (chance <= 95)
{
af.duration = 0;
affect_to_char(ch,&af);
return send_to_char("You failed to plant the explosive, but remained uncaught.\n\r",ch);
}
else
{
char buf[MSL];
sprintf(buf,"%s is attempting to plant something within my possessions!",!IS_NPC(ch) ? ch->name : ch->short_descr);
do_yell(victim,buf);
multi_hit(victim,ch, TYPE_UNDEFINED);
af.duration = bombDuration / 3;
affect_to_char(ch,&af);
return send_to_char("You failed to plant the explosive and revealed your intentions!\n\r",ch);
}
}
void do_undisguise( CHAR_DATA *ch, char *argument ) {
if (get_skill(ch,skill_lookup("disguise")) <= 0)
return send_to_char("Huh?\n\r",ch);
if (is_affected(ch,skill_lookup("disguise"))) {
send_to_char("You toss your disguise aside.\n\r",ch);
affect_strip(ch,skill_lookup("disguise"));
}
else send_to_char("You aren't wearing a disguise!\n\r",ch);
return;
}
void do_disguise( CHAR_DATA *ch, char *argument )
{
OBJ_DATA *corpse;
char af_buf[MSL], buf[MSL];
if (is_affected(ch,skill_lookup("disguise timer")))
return send_to_char("You have not yet readied yourself to craft a disguise.\n\r",ch);
if (is_affected(ch,skill_lookup("disguise")))
return send_to_char("You are already disguised!\n\r",ch);
if (argument[0] == '\0')
return send_to_char("You must specify a target.\n\r",ch);
if ((corpse = get_obj_here(ch, argument)) == NULL)
return send_to_char("That isn't here.\n\r",ch);
sprintf(af_buf,"disguised as %s",corpse->corpse_of);
AFFECT_DATA af;
init_affect(&af);
af.duration = ch->level;
af.where = TO_AFFECTS;
af.aftype = AFT_SKILL;
af.level = ch->level;
af.type = skill_lookup("disguise");
af.affect_list_msg = str_dup(af_buf);
affect_to_char(ch, &af);
af.type = skill_lookup("disguise timer");
af.duration = ch->level / 10;
af.affect_list_msg = str_dup("prevents usage of disguise");
affect_to_char(ch, &af);
ch->name = str_dup(corpse->corpse_of);
sprintf(buf,"Using the corpse and its belongings, you cleverly disguise yourself as %s!\n\r",corpse->corpse_of);
send_to_char(buf,ch);
return;
}
int get_rand_skill(CHAR_DATA *ch, bool ignore_perfected)
{
int sn = 0;
while (1) {
sn = number_range(0, MAX_SKILL);
if (!ignore_perfected) {
if (ch->pcdata->learned[sn] > 1)
return sn;
} else {
if (ch->pcdata->learned[sn] > 1 && ch->pcdata->learned[sn] < 100)
return sn;
}
}
}