/***************************************************************************
* 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-1995 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 Rom24/doc/rom.license *
***************************************************************************/
/***************************************************************************
* ROT 1.4 is copyright 1996-1997 by Russ Walsh *
* By using this code, you have agreed to follow the terms of the *
* ROT license, in the file doc/rot.license *
***************************************************************************/
#if defined(macintosh)
#include <types.h>
#include <time.h>
#else
#include <sys/types.h>
#include <sys/time.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "merc.h"
#include "magic.h"
/* command procedures needed */
DECLARE_DO_FUN(do_help );
DECLARE_DO_FUN(do_say );
DECLARE_DO_FUN(do_handle );
DECLARE_DO_FUN(do_side_kick );
DECLARE_DO_FUN(do_spin_kick );
DECLARE_DO_FUN(do_blindness_dust);
DECLARE_DO_FUN(do_will_of_iron );
//DECLARE_DO_FUN(do_spinkick );
DECLARE_DO_FUN(do_purify_body );
DECLARE_DO_FUN(do_healing_trance );
DECLARE_DO_FUN(do_yell );
DECLARE_DO_FUN(do_rest );
DECLARE_DO_FUN(do_sleep );
int handling_improve args((CHAR_DATA *ch, sh_int sn));
void check_ground_stomp args((CHAR_DATA *ch,CHAR_DATA *victim,int chance,int dam));
void check_follow_through args((CHAR_DATA *ch, CHAR_DATA *victim, int dam));
bool check_dispel args(( int dis_level, CHAR_DATA *victim, int sn));
bool is_safe_quiet args ((CHAR_DATA * ch, CHAR_DATA * victim));
void improve_toughness args ((CHAR_DATA *ch));
/* used to get new skills */
void do_gain(CHAR_DATA *ch, char *argument)
{
char buf[MAX_STRING_LENGTH];
char arg[MAX_INPUT_LENGTH];
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
CHAR_DATA *trainer;
int sn = 0;
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))
break;
if (trainer == NULL || !can_see(ch,trainer))
{
send_to_char("You can't do that here.\n\r",ch);
return;
}
strcpy(arg2,argument);
argument = one_argument(argument,arg);
strcpy(arg1,argument);
if (arg[0] == '\0')
{
do_say(trainer,"{_Pardon me?{x");
return;
}
if (!str_prefix(arg,"list"))
{
int col;
col = 0;
sprintf(buf, "%-18s %-5s %-18s %-5s %-18s %-5s\n\r",
"skill","cost","skill","cost","skill","cost");
send_to_char(buf,ch);
for (sn = 0; sn < MAX_SKILL; sn++)
{
if (skill_table[sn].name == NULL)
break;
if (!ch->pcdata->learned[sn]
&& skill_table[sn].skill_level[ch->class] <= LEVEL_HERO)
{
sprintf(buf,"{&%-18s {8%-5d{x ",
skill_table[sn].name,skill_table[sn].rating[ch->class]);
send_to_char(buf,ch);
if (++col % 3 == 0)
send_to_char("\n\r",ch);
}
}
if (col % 3 != 0)
send_to_char("\n\r",ch);
return;
}
if (!str_prefix(arg,"convert"))
{
if (ch->practice < 6)
{
act("$N tells you 'You are not yet ready.{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
if (!str_cmp(arg1,"all"))
{
act("$N converts all your practices to trains.",ch,NULL,trainer,TO_CHAR);
while(ch->practice >= 6)
{ //Do it. All your practice are belong to train.
ch->practice -= 6;
ch->train += 1;
}
return;
}
else
{
act("$N helps you apply your practice to training",
ch,NULL,trainer,TO_CHAR);
ch->practice -= 6;
ch->train +=1 ;
return;
}
}
if (!str_prefix(arg,"study"))
{
if (ch->train < 1)
{
act("$N tells you 'You are not yet ready.{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
if (!str_cmp(arg1,"all"))
{
act("$N converts all your trains to practices.",ch,NULL,trainer,TO_CHAR);
while(ch->train > 0)
{ //Do it. All your trains are belong to practice.
ch->practice += 6;
ch->train -= 1;
}
return;
}
else
{
act("$N helps you apply your training to practice",
ch,NULL,trainer,TO_CHAR);
ch->train -= 1;
ch->practice += 6;
return;
}
}
if (!str_prefix(arg,"points"))
{
if (ch->train < 2)
{
act("$N tells you '{_You are not yet ready.{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
if (ch->pcdata->points <= 40)
{
act("$N tells you '{_There would be no point in that.{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
act("$N trains you, and you feel more at ease with your skills.",
ch,NULL,trainer,TO_CHAR);
ch->train -= 2;
ch->pcdata->points -= 1;
ch->exp = (long)exp_per_level(ch,ch->pcdata->points) * ch->level;
return;
}
/* else add a group/skill */
sn = skill_lookup(arg2);
if (sn == skill_lookup("conceal"))
{
send_to_char("You cannot gain that.\n\r",ch);
return;
}
if (sn > -1)
{
if (ch->pcdata->learned[sn])
{
act("$N tells you '{_You already know that skill!{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
if (skill_table[sn].skill_level[ch->class] > LEVEL_HERO)
{
act("$N tells you '{_That skill is beyond your powers.{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
if (ch->train < skill_table[sn].rating[ch->class])
{
act("$N tells you '{_You are not yet ready for that skill.{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
/* add the skill */
ch->pcdata->learned[sn] = 1;
ch->pcdata->learnlvl[sn] = skill_table[sn].skill_level[ch->class];
act("$N trains you in the art of $t",
ch,skill_table[sn].name,trainer,TO_CHAR);
ch->train -= skill_table[sn].rating[ch->class];
return;
}
act("$N tells you '{_I do not understand...{x'",ch,NULL,trainer,TO_CHAR);
}
/* RT spells and skills show the players spells (or skills) */
void do_garrote( CHAR_DATA *ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
int chance;
one_argument( argument, arg );
if ( (chance = get_skill(ch,gsn_garrote)) == 0
|| (!IS_NPC(ch)
&& ch->level < skill_table[gsn_garrote].skill_level[ch->class]))
{
send_to_char("Garrote? What's that?{x\n\r",ch);
return;
}
if (arg[0] == '\0')
{
send_to_char("Garrote whom?\n\r",ch);
return;
}
if (ch->fighting != NULL)
{
send_to_char("{hYou're facing the wrong end.{x\n\r",ch);
return;
}
else 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( "How can you sneak up on yourself?\n\r", ch );
return;
}
if ( is_safe( ch, victim ) )
return;
if (IS_NPC(victim) &&
victim->fighting != NULL &&
!is_same_group(ch,victim->fighting)
&& !IS_SET(victim->in_room->room_flags, ROOM_ARENA))
{
send_to_char("Kill stealing is not permitted.\n\r",ch);
return;
}
if ( victim->hit < victim->max_hit / 4)
{
act( "$N is hurt and suspicious ... you can't sneak up.",
ch, NULL, victim, TO_CHAR );
return;
}
if ( ( ch->fighting == NULL )
&& ( !IS_NPC( ch ) )
&& ( !IS_NPC( victim ) ) )
{
ch->attacker = TRUE;
victim->attacker = FALSE;
}
/* dexterity */
chance += get_curr_stat(ch,STAT_DEX);
chance -= get_curr_stat(victim,STAT_DEX)/2;
/* speed */
if (IS_SET(ch->off_flags,OFF_FAST) || IS_AFFECTED(ch,AFF_HASTE))
chance += 25;
if (IS_SET(victim->off_flags,OFF_FAST) || IS_AFFECTED(victim,AFF_HASTE))
chance -= 10;
/* level */
chance += (ch->level - victim->level) * 4;
/* sloppy hack to prevent false zeroes */
if (chance % 5 == 0)
chance += 1;
/* now the attack */
if (number_percent() * 2 < chance)
{
AFFECT_DATA af;
act("{k$n is choked by a wire around the neck!{x",victim,NULL,NULL,TO_ROOM);
act("{i$n slips a wire around your neck!{x",ch,NULL,victim,TO_VICT);
multi_hit (ch, victim, gsn_garrote);
send_to_char("{7You choke and gag!{x\n\r",victim);
check_improve(ch,gsn_garrote,TRUE,2);
WAIT_STATE(ch,skill_table[gsn_garrote].beats);
/* Leave the garrote on the choke the shit out of em */
af.where = TO_AFFECTS2;
af.type = gsn_garrote;
af.level = ch->level;
af.duration = 3;
af.location = APPLY_HITROLL;
af.modifier = -150;
af.bitvector = AFF2_GARROTE;
affect_to_char(victim,&af);
}
else
{
damage(ch,victim,0,gsn_garrote,DAM_NONE,TRUE, 0);
check_improve(ch,gsn_garrote,FALSE,2);
WAIT_STATE(ch,skill_table[gsn_garrote].beats);
}
}
void do_spells(CHAR_DATA *ch, char *argument)
{
char spell_list[LEVEL_HERO][MAX_STRING_LENGTH];
char spell_columns[LEVEL_HERO];
int sn,lev,mana;
bool found = FALSE;
char buf[MAX_STRING_LENGTH];
char arg[MAX_STRING_LENGTH];
bool ShowColors = TRUE;
bool fWhite = FALSE;
bool fRed = FALSE;
bool fBlue = FALSE;
bool fGreen = FALSE;
bool fOrange = FALSE;
bool fBlack = FALSE;
if (IS_NPC(ch))
return;
argument = one_argument(argument,arg);
if(arg[0] != '\0')
{
if(!str_cmp(arg,"white"))
{
fWhite = TRUE;
ShowColors = FALSE;
printf_to_char(ch,"Proficiecy in {7White{x Magic: {&%d{x.\n\r",ch->magic[MAGIC_WHITE]);
}
if(!str_cmp(arg,"red"))
{
fRed = TRUE;
ShowColors = FALSE;
printf_to_char(ch,"Proficiecy in {!Red{x Magic: {&%d{x.\n\r",ch->magic[MAGIC_RED]);
}
if(!str_cmp(arg,"blue"))
{
fBlue = TRUE;
ShowColors = FALSE;
printf_to_char(ch,"Proficiecy in {$Blue{x Magic: {&%d{x.\n\r",ch->magic[MAGIC_BLUE]);
}
if(!str_cmp(arg,"green"))
{
fGreen = TRUE;
ShowColors = FALSE;
printf_to_char(ch,"Proficiecy in {@Green{x Magic: {&%d{x.\n\r",ch->magic[MAGIC_GREEN]);
}
if(!str_cmp(arg,"black"))
{
fBlack = TRUE;
ShowColors = FALSE;
printf_to_char(ch,"Proficiecy in {8Black{x Magic: {&%d{x.\n\r",ch->magic[MAGIC_BLACK]);
}
if(!str_cmp(arg,"orange"))
{
fOrange = TRUE;
ShowColors = FALSE;
printf_to_char(ch,"Proficiecy in {3Orange{x Magic: {&%d{x.\n\r",ch->magic[MAGIC_ORANGE]);
}
}
/* initilize data */
for (lev = 0; lev < LEVEL_HERO; lev++)
{
spell_columns[lev] = 0;
spell_list[lev][0] = '\0';
}
for (sn = 0; sn < MAX_SKILL; sn++)
{
if (skill_table[sn].name == NULL)
break;
/* if (skill_table[sn].skill_level[ch->class] < LEVEL_HERO &&
skill_table[sn].spell_fun != spell_null &&
ch->pcdata->learned[sn] > 0)
{
found = TRUE;
lev = skill_table[sn].skill_level[ch->class]; */
lev = ch->pcdata->learnlvl[sn];
if (lev < LEVEL_HERO &&
skill_table[sn].spell_fun != spell_null &&
ch->pcdata->learned[sn] > 0)
{
found = TRUE;
if (ch->level < lev)
{
if(!ShowColors)
{
if(fWhite && !IS_SPELL_WHITE(sn))
continue;
else if(fRed && !IS_SPELL_RED(sn))
continue;
else if(fBlue && !IS_SPELL_BLUE(sn))
continue;
else if(fGreen && !IS_SPELL_GREEN(sn))
continue;
else if(fOrange && !IS_SPELL_ORANGE(sn))
continue;
else if(fBlack && !IS_SPELL_BLACK(sn))
continue;
}
if(IS_SPELL_WHITE(sn))
sprintf(buf,"{&%-18s{x {#n/a{x ", skill_table[sn].name);
else if(IS_SPELL_RED(sn))
sprintf(buf,"{!%-18s{x {#n/a{x ", skill_table[sn].name);
else if(IS_SPELL_BLUE(sn))
sprintf(buf,"{$%-18s{x {#n/a{x ", skill_table[sn].name);
else if(IS_SPELL_GREEN(sn))
sprintf(buf,"{@%-18s{x {#n/a{x ", skill_table[sn].name);
else if(IS_SPELL_ORANGE(sn))
sprintf(buf,"{3%-18s{x {#n/a{x ", skill_table[sn].name);
else if(IS_SPELL_BLACK(sn))
sprintf(buf,"{8%-18s{x {#n/a{x ", skill_table[sn].name);
else
sprintf(buf,"{C%-18s{x {#n/a{x ", skill_table[sn].name);
}
else
{
if(!ShowColors)
{
if(fWhite && !IS_SPELL_WHITE(sn))
continue;
else if(fRed && !IS_SPELL_RED(sn))
continue;
else if(fBlue && !IS_SPELL_BLUE(sn))
continue;
else if(fGreen && !IS_SPELL_GREEN(sn))
continue;
else if(fOrange && !IS_SPELL_ORANGE(sn))
continue;
else if(fBlack && !IS_SPELL_BLACK(sn))
continue;
}
mana = UMAX(skill_table[sn].min_mana,
100/(2 + ch->level - lev));
if(IS_SPELL_WHITE(sn))//maybe put * 3 or 2 after [sn] --bree learned
sprintf(buf,"{&%-18s {#%3d{x mana {@({&%d{@){x ",skill_table[sn].name,mana,ch->pcdata->learned[sn]);
else if(IS_SPELL_BLUE(sn))
sprintf(buf,"{$%-18s {#%3d{x mana {@({&%d{@){x ",skill_table[sn].name,mana,ch->pcdata->learned[sn]);
else if(IS_SPELL_RED(sn))
sprintf(buf,"{!%-18s {#%3d{x mana {@({&%d{@){x ",skill_table[sn].name,mana,ch->pcdata->learned[sn]);
else if(IS_SPELL_GREEN(sn))
sprintf(buf,"{@%-18s {#%3d{x mana {@({&%d{@){x ",skill_table[sn].name,mana,ch->pcdata->learned[sn]);
else if(IS_SPELL_ORANGE(sn))
sprintf(buf,"{3%-18s {#%3d{x mana {@({&%d{@){x ",skill_table[sn].name,mana,ch->pcdata->learned[sn]);
else if(IS_SPELL_BLACK(sn))
sprintf(buf,"{8%-18s {#%3d{x mana {@({&%d{@){x ",skill_table[sn].name,mana,ch->pcdata->learned[sn]);
else
sprintf(buf,"{C%-18s {#%3d{x mana {@({&%d{@){x ",skill_table[sn].name,mana,ch->pcdata->learned[sn]);
}
if (spell_list[lev][0] == '\0')
sprintf(spell_list[lev],"\n\r{BLevel{x {&%2d{x: %s",lev,buf);
else /* append */
{
if ( ++spell_columns[lev] % 2 == 0)
strcat(spell_list[lev],"\n\r ");
strcat(spell_list[lev],buf);
}
}
}
/* return results */
if (!found)
{
send_to_char("You know no spells.\n\r",ch);
return;
}
for (lev = 0; lev < LEVEL_HERO; lev++)
if (spell_list[lev][0] != '\0')
send_to_char(spell_list[lev],ch);
send_to_char("\n\r",ch);
}
void do_skills(CHAR_DATA *ch, char *argument)
{
char skill_list[LEVEL_HERO][MAX_STRING_LENGTH];
char skill_columns[LEVEL_HERO];
int sn,lev;
bool found = FALSE;
char buf[MAX_STRING_LENGTH];
if (IS_NPC(ch))
return;
/* initilize data */
for (lev = 0; lev < LEVEL_HERO; lev++)
{
skill_columns[lev] = 0;
skill_list[lev][0] = '\0';
}
for (sn = 0; sn < MAX_SKILL; sn++)
{
if (skill_table[sn].name == NULL )
break;
lev = ch->pcdata->learnlvl[sn];
/* if (skill_table[sn].skill_level[ch->class] < LEVEL_HERO && */
if (lev < LEVEL_HERO &&
skill_table[sn].spell_fun == spell_null &&
ch->pcdata->learned[sn] > 0)
{
found = TRUE;
// lev = skill_table[sn].skill_level[ch->class];
if (ch->level < lev)
sprintf(buf,"{R%-18s{x {@n/a{x ", skill_table[sn].name);
else
sprintf(buf,"{R%-18s{x {@%3d%%{x ",skill_table[sn].name,
ch->pcdata->learned[sn]);
if (skill_list[lev][0] == '\0')
sprintf(skill_list[lev],"\n\r{yLevel {&%2d{x: %s",lev,buf);
else /* append */
{
if ( ++skill_columns[lev] % 2 == 0)
strcat(skill_list[lev],"\n\r ");
strcat(skill_list[lev],buf);
}
}
}
/* return results */
if (!found)
{
send_to_char("You know no skills.\n\r",ch);
return;
}
for (lev = 0; lev < LEVEL_HERO; lev++)
if (skill_list[lev][0] != '\0')
send_to_char(skill_list[lev],ch);
send_to_char("\n\r",ch);
}
/* shows skills, groups and costs (only if not bought) */
void list_group_costs(CHAR_DATA *ch)
{
char buf[100];
int sn,col;
if (IS_NPC(ch))
return;
col = 0;
sprintf(buf,"%-18s %-5s %-18s %-5s %-18s %-5s\n\r","skill","cp","skill","cp","skill","cp");
send_to_char(buf,ch);
for (sn = 0; sn < MAX_SKILL; sn++)
{
if (skill_table[sn].name == NULL)
break;
if (!ch->gen_data->skill_chosen[sn]
&& ch->pcdata->learned[sn] < 1
&& skill_table[sn].skill_level[ch->class] < LEVEL_HERO )
{
sprintf(buf,"%-18s %-5d ",skill_table[sn].name,
skill_table[sn].rating[ch->class]);
send_to_char(buf,ch);
if (++col % 3 == 0)
send_to_char("\n\r",ch);
/* Bad Hack but should work
* Sets class gainable skills to 0
* leaves ungainables at -1
*/
ch->pcdata->learned[sn] = 0;
}
}
if ( col % 3 != 0 )
send_to_char( "\n\r", ch );
send_to_char("\n\r",ch);
sprintf(buf,"Creation points: %d\n\r",ch->pcdata->points);
send_to_char(buf,ch);
sprintf(buf,"Experience per level: %ld\n\r",
exp_per_level(ch,ch->gen_data->points_chosen));
send_to_char(buf,ch);
return;
}
void list_group_chosen(CHAR_DATA *ch)
{
char buf[100];
int sn,col;
if (IS_NPC(ch))
return;
col = 0;
sprintf(buf,"%-18s %-5s %-18s %-5s %-18s %-5s","skill","cp","skill","cp","skill","cp\n\r");
send_to_char(buf,ch);
for (sn = 0; sn < MAX_SKILL; sn++)
{
if (skill_table[sn].name == NULL)
break;
if (ch->gen_data->skill_chosen[sn]
&& skill_table[sn].skill_level[ch->class] <= LEVEL_HERO)
{
sprintf(buf,"%-18s %-5d ",skill_table[sn].name,
skill_table[sn].rating[ch->class]);
send_to_char(buf,ch);
if (++col % 3 == 0)
send_to_char("\n\r",ch);
}
}
if ( col % 3 != 0 )
send_to_char( "\n\r", ch );
send_to_char("\n\r",ch);
sprintf(buf,"Creation points: %d\n\r",ch->gen_data->points_chosen);
send_to_char(buf,ch);
sprintf(buf,"Experience per level: %ld\n\r",
exp_per_level(ch,ch->gen_data->points_chosen));
send_to_char(buf,ch);
return;
}
long exp_per_level(CHAR_DATA *ch, int points)
{
long expl,inc,epl;
if (IS_NPC(ch))
return 1000;
expl = 1000;
inc = 500;
if (points < 40)
return 1000 * pc_race_table[ch->race].class_mult[ch->class]/100;
/* processing */
points -= 40;
while (points > 9)
{
expl += (long)inc;
points -= 10;
if (points > 9)
{
expl += (long)inc;
inc *= 2;
points -= 10;
}
}
expl += (long)points * (long)inc / 10;
epl = (long)expl * (long)pc_race_table[ch->race].class_mult[ch->class]/100;
if(ch->pcdata->tier > 2)
{
/* Temporary check */
if(epl < 3000)
epl += (long)(epl * 8 / 100);
else if(epl < 6000)
epl += (long)(epl * 4 / 100);
else
epl += (long)(epl * 2 / 200);
}
else if(ch->pcdata->tier > 1)
{
epl += (long)(epl * 4 / 100);
}
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 sn;
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;
}
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].skill_level[ch->class] > LEVEL_HERO)
{
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;
ch->pcdata->points += skill_table[sn].rating[ch->class];
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;
}
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;
ch->pcdata->points -= skill_table[sn].rating[ch->class];
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;
}
return FALSE;
}
int spell_avail( CHAR_DATA *ch, const char *name )
{
/* checks to see if a spell is available to a class */
int sn, found = -1;
if (IS_NPC(ch))
return skill_lookup(name);
for ( sn = 0; sn < MAX_SKILL; sn++ )
{
if (skill_table[sn].name == NULL)
break;
if (LOWER(name[0]) == LOWER(skill_table[sn].name[0])
&& !str_prefix(name,skill_table[sn].name))
{
if (skill_table[sn].skill_level[ch->class] <= LEVEL_HERO)
return sn;
}
}
return found;
}
/* checks for skill improvement */
void check_improve( CHAR_DATA *ch, int sn, bool success, int multiplier )
{
int chance;
char buf[100];
if (IS_NPC(ch))
return;
sn = handling_improve(ch,sn);
if (ch->level < skill_table[sn].skill_level[ch->class]
|| skill_table[sn].skill_level[ch->class] > LEVEL_HERO
|| ch->pcdata->learned[sn] == 0
|| ch->pcdata->learned[sn] == 100)
return; /* skill is not known */
/* check to see if the character has a chance to learn */
chance = 10 * int_app[get_curr_stat(ch,STAT_INT)].learn;
chance /= ( multiplier
* skill_table[sn].rating[ch->class]
* 4)+1;
chance += ch->level;
if (number_range(1,1000) > chance)
return;
/* now that the character has a CHANCE to learn, see if they really have */
if (success)
{
chance = URANGE(5,100 - ch->pcdata->learned[sn], 95);
if (number_percent() < chance)
{
ch->pcdata->learned[sn]++;
sprintf(buf,"{GYou have become better at {R%s{G! ({R%d{G%%){x\n\r",
skill_table[sn].name, ch->pcdata->learned[sn]);
send_to_char(buf,ch);
gain_exp(ch,2 * skill_table[sn].rating[ch->class]);
}
}
else
{
chance = URANGE(5,ch->pcdata->learned[sn]/2,30);
if (number_percent() < chance)
{
ch->pcdata->learned[sn] += number_range(1,3);
ch->pcdata->learned[sn] = UMIN(ch->pcdata->learned[sn],100);
sprintf(buf,
"{GYou learn from your mistakes, and your {R%s {Gskill improves. ({R%d{G%%){x\n\r",
skill_table[sn].name, ch->pcdata->learned[sn]);
send_to_char(buf,ch);
gain_exp(ch,2 * skill_table[sn].rating[ch->class]);
}
}
}
/* use for processing a skill or group for addition */
void group_add( CHAR_DATA *ch, const char *name, bool deduct)
{
int sn;
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;
if (deduct)
ch->pcdata->points += skill_table[sn].rating[ch->class];
}
return;
}
}
/* used for processing a skill or group for deletion -- no points back! */
void group_remove(CHAR_DATA *ch, const char *name)
{
int sn;
sn = skill_lookup(name);
if (sn != -1)
{
ch->pcdata->learned[sn] = 0;
return;
}
}
void do_showclass(CHAR_DATA *ch, char* argument)
{
char buf[100];
int sn,col,class;
if (IS_NPC(ch))
return;
if ( (class = class_lookup(argument)) == -1)
{
send_to_char("That's not a valid class",ch);
return;
}
col = 0;
sprintf(buf,"%-18s %-5s %-18s %-5s %-18s %-5s\n\r","skill","cp","skill","cp","skill","cp");
send_to_char(buf,ch);
for (sn = 0; sn < MAX_SKILL; sn++)
{
if (skill_table[sn].name == NULL)
break;
if ( skill_table[sn].skill_level[class] < LEVEL_HERO )
{
sprintf(buf,"%-18s %-2d(%-3d) ",skill_table[sn].name,
skill_table[sn].rating[class],skill_table[sn].skill_level[class]);
send_to_char(buf,ch);
if (++col % 3 == 0)
send_to_char("\n\r",ch);
}
}
if ( col % 3 != 0 )
send_to_char( "\n\r", ch );
send_to_char("\n\r", ch );
return;
}
void do_showskill(CHAR_DATA *ch, char* argument)
{
int class;
int skill;
char buf[MAX_STRING_LENGTH];
skill = skill_lookup(argument);
if ( skill == -1 )
{
send_to_char("That's not a skill or spell.\n\r",ch);
return;
}
sprintf(buf,"The following classes get '%s':\n\r",argument);
for ( class = 0; class < MAX_CLASS; class++ )
{
if(skill_table[skill].skill_level[class] < LEVEL_HERO)
{
if ( class > 0 )
strcat( buf, " " );
strcat( buf, class_table[class].name );
}
}
strcat( buf, ".\n\r" );
send_to_char(buf,ch);
return;
}
/* Monk Stuff -- Skyntil */
void do_open_palming(CHAR_DATA *ch,char *argument)
{
AFFECT_DATA af;
int chance;
if ( (chance = get_skill(ch,gsn_palm)) == 0
|| ch->pcdata->learned[gsn_palm] < 1)
{
send_to_char("You don't have the ability to use open palm striking martial arts.\n\r",ch);
return;
}
if (IS_NPC(ch) && IS_AFFECTED(ch,AFF_CHARM))
return;
if (is_affected(ch,gsn_palm))
{
send_to_char("Your palms are already tense.\n\r",ch);
return;
}
if (get_eq_char(ch,WEAR_WIELD) != NULL
|| get_eq_char(ch,WEAR_SECONDARY) != NULL)
{
send_to_char("You can't start using open palm striking while using weapons.\n\r",ch);
return;
}
if (number_percent() >= chance)
{
send_to_char("Your try to tense the nerves in your hands, but fail.\n\r",ch);
check_improve(ch,gsn_palm,FALSE,2);
return;
}
act("$n goes into a trance and $s hands become deadly weapons.",ch,0,0,TO_ROOM);
send_to_char("You feel your mind relax as the nerves in your hands tense.\n\r",ch);
af.where = TO_AFFECTS;
af.type = gsn_palm;
af.location = 0;
af.modifier = 0;
af.duration = (ch->level/4);
af.level = ch->level;
af.bitvector = 0;
affect_to_char(ch,&af);
check_improve(ch,gsn_palm,TRUE,2);
WAIT_STATE(ch,6);
return;
}
void do_martial_arts(CHAR_DATA *ch,char *argument)
{
AFFECT_DATA af;
int chance;
if ( (chance = get_skill(ch,gsn_martial_arts)) == 0
|| ch->pcdata->learned[gsn_martial_arts] < 1 )
{
send_to_char("You don't know any martial arts.\n\r",ch);
return;
}
if (ch->class == CLASS_MONK)
{
if (is_affected(ch,gsn_martial_arts))
{
if (ch->fighting == NULL)
{
send_to_char("You stop focusing on the art of combat and find inner peace.\n\r",ch);
affect_strip(ch,gsn_martial_arts);
WAIT_STATE(ch,18);
return;
}
else
{
send_to_char("You are too busy fighting to do that!\n\r",ch);
return;
}
}
}
else if (is_affected(ch,gsn_martial_arts))
{
send_to_char("You are already focused on combat.\n\r",ch);
return;
}
if ((get_eq_char(ch,WEAR_WIELD) != NULL
|| get_eq_char(ch,WEAR_SECONDARY) != NULL) && ch->class == CLASS_MONK)
{
send_to_char("You cannot practice this skill using weapons.\n\r",ch);
return;
}
if (number_percent() >= chance)
{
send_to_char("You build up intense focus but lose concentration.\n\r",ch);
check_improve(ch,gsn_martial_arts,FALSE,2);
return;
}
act("$n's face clouds with a look of deadly concentration.",ch,0,0,TO_ROOM);
send_to_char("You feel your body's focus increase toward mastery.\n\r",ch);
af.where = TO_AFFECTS;
af.type = gsn_martial_arts;
af.location = 0;
af.modifier = 0;
if (ch->class == CLASS_MONK)
{
af.duration = -1;
}
else
{
af.duration = ch->level/5;
}
af.level = ch->level;
af.bitvector = 0;
affect_to_char(ch,&af);
WAIT_STATE(ch,6);
return;
}
void lose_skill(CHAR_DATA *ch, int skill)
{
int gain = 0; /* Gain from losing */
int prac_gain = 0;
char log_name[MSL];
char log_buf[100];
// If your class loses a skill
if(!IS_IMMORTAL(ch) && !class_has_skill(ch->class, skill))
{
gain = skill_table[skill].rating[ch->class];
if(ch->pcdata->learned[skill] >= 75)
prac_gain = 3;
else if(ch->pcdata->learned[skill] >= 50)
prac_gain = 2;
else if(ch->pcdata->learned[skill] >= 25)
prac_gain = 1;
else
prac_gain = 0;
ch->train += gain;
ch->practice += prac_gain;
printf_to_char(ch,"You lose the %s skill and gain %d trains.\n\r",
skill_table[skill].name,gain);
ch->pcdata->learned[skill] = -1;
ch->pcdata->learnlvl[skill] = 102;
sprintf(log_name,"%s",ch->name);
sprintf(log_buf," has lost the %s skill.", skill_table[skill].name);
strcat(log_name, log_buf);
log_string(log_name);
}
return;
}
void gain_skill(CHAR_DATA *ch, int skill)
{
// You figure it out
if(class_has_skill(ch->class, skill) && ch->pcdata->learned[skill] < 1)
{
if(ch->level > skill_table[skill].skill_level[ch->class])
{
ch->pcdata->learned[skill] = 75;
ch->pcdata->learnlvl[skill] = skill_table[skill].skill_level[ch->class];
}
else
{
ch->pcdata->learned[skill] = 1;
ch->pcdata->learnlvl[skill] = skill_table[skill].skill_level[ch->class];
}
printf_to_char(ch,"You gain the %s skill at %d percent.\n\r",
skill_table[skill].name,ch->pcdata->learned[skill]);
}
return;
}
/* Gain a skill into the gain list */
void gain_skill_gain(CHAR_DATA *ch, int skill)
{
char log_name[MSL];
char log_buf[100];
if(class_has_skill(ch->class, skill) && ch->pcdata->learned[skill] < 0)
{
ch->pcdata->learned[skill] = 0;
printf_to_char(ch,"You are now able to gain the %s skill.\n\r",
skill_table[skill].name);
sprintf(log_name,"%s",ch->name);
sprintf(log_buf," can now gain the %s skill.", skill_table[skill].name);
strcat(log_name, log_buf);
log_string(log_name);
}
return;
}
bool has_skill(CHAR_DATA *ch,int skill)
{
return IS_NPC(ch) ? TRUE : (ch->level >= ch->pcdata->learnlvl[skill]);
}
bool class_has_skill(int class, int skill)
{
return (skill_table[skill].skill_level[class] < 102);
}
bool has_learned_skill(CHAR_DATA *ch,int skill)
{
return IS_NPC(ch) ? TRUE : (ch->pcdata->learned[skill] > 0);
}
bool has_gain(CHAR_DATA *ch,int skill)
{
if(ch->pcdata->learned[skill] == 0)
return TRUE;
else
return FALSE;
}
int handling_improve(CHAR_DATA *ch, sh_int sn)
{
sh_int wsn = -1;
if(ch->pcdata->learned[sn] < 100)
return sn;
if(sn == gsn_sword)
wsn = gsn_sword2;
else if(sn == gsn_axe)
wsn = gsn_axe2;
else if(sn == gsn_hand_to_hand)
wsn = gsn_hand2;
else if(sn == gsn_dagger)
wsn = gsn_dagger2;
else if(sn == gsn_polearm)
wsn = gsn_polearm2;
else if(sn == gsn_whip)
wsn = gsn_whip2;
else if(sn == gsn_spear)
wsn = gsn_spear2;
else if(sn == gsn_mace)
wsn = gsn_mace2;
else if(sn == gsn_flail)
wsn = gsn_flail2;
else if(sn == gsn_dual_wield)
wsn = gsn_dual_wield2;
if(wsn == -1)
return sn;
return wsn;
}
void do_handle(CHAR_DATA *ch, char *argument)
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *trainer;
sh_int sn,wsn = -1;
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,"What do you wish to learn?");
do_say(trainer,"I can teach you how to handle your weapon better perhaps?");
return;
}
if(str_cmp(arg,"sword")
&& str_cmp(arg,"dagger")
&& str_cmp(arg,"polearm")
&& str_cmp(arg,"spear")
&& str_cmp(arg,"flail")
&& str_cmp(arg,"mace")
&& str_cmp(arg,"whip")
&& str_cmp(arg,"axe")
&& str_cmp(arg,"dual wield") )
{
do_say(trainer,"Pardon me?");
return;
}
sn = skill_lookup(arg);
if (ch->pcdata->learned[sn] < 100 && sn != gsn_dual_wield)
{
act("$N tells you 'You are not yet ready to learn with that weapon.'",ch,NULL,trainer,TO_CHAR);
return;
}
else if(ch->pcdata->learned[sn] < 100 && sn == gsn_dual_wield)
{
act("$N tells you 'You are not yet ready to learn dual weapon mastery.'",ch,NULL,trainer,TO_CHAR);
return;
}
if(sn == gsn_sword)
wsn = gsn_sword2;
else if(sn == gsn_axe)
wsn = gsn_axe2;
else if(sn == gsn_dagger)
wsn = gsn_dagger2;
else if(sn == gsn_polearm)
wsn = gsn_polearm2;
else if(sn == gsn_whip)
wsn = gsn_whip2;
else if(sn == gsn_spear)
wsn = gsn_spear2;
else if(sn == gsn_mace)
wsn = gsn_mace2;
else if(sn == gsn_flail)
wsn = gsn_flail2;
else if(sn == gsn_dual_wield)
wsn = gsn_dual_wield2;
if(wsn == -1)
return;
if(wsn == gsn_dual_wield2)
{
ch->pcdata->learned[wsn] = 1;
ch->pcdata->learnlvl[wsn] = skill_table[wsn].skill_level[ch->class];
act("$N teaches how to better handle your weapon!",ch,NULL,trainer,TO_CHAR);
return;
}
if(ch->class == CLASS_ASSASSIN && !IS_IMMORTAL(ch) && wsn == gsn_dagger2)
{
ch->pcdata->learned[wsn] = 1;
act("$N teaches how to better handle your weapon!",ch,NULL,trainer,TO_CHAR);
return;
}
if(ch->class != CLASS_CRUSADER && !IS_IMMORTAL(ch))
{
do_say(trainer,"You cannot learn to better handle that weapon.");
return;
}
ch->pcdata->learned[wsn] = 1;
act("$N teaches how to better handle your weapon!",ch,NULL,trainer,TO_CHAR);
/*if(ch->level == LEVEL_HERO)
ch->practice += 2;*/
return;
}
// New Stuff 01/2005 -- Skyn.
// Ground Stomp
void check_ground_stomp(CHAR_DATA *ch,CHAR_DATA *victim,int chance,int dam)
{
if (chance < 10)
return;
if (dam == 0)
return;
chance = get_skill(ch,gsn_ground_stomp);
chance /= 2;
chance -= number_range(5,15);
chance = URANGE(5,chance,50);
if (!has_skill(ch,gsn_ground_stomp))
return;
if (number_percent() > chance)
{
check_improve(ch,gsn_ground_stomp,FALSE,3);
return;
}
act("You land your foot hard on $N's body.",ch,0,victim,TO_CHAR);
act("$n stomps $N's body with brutal force.",ch,0,victim,TO_NOTVICT);
act("$n lands his foot hard against your body.",ch,0,victim,TO_VICT);
check_improve(ch,gsn_ground_stomp,TRUE,2);
dam = dam * 4;
dam = dam / 5;
if(number_percent() < 10)
{
act("You hit $N critically!",ch,0,victim,TO_CHAR);
dam *= 3/2;
}
damage(ch,victim,dam,gsn_ground_stomp,DAM_BASH,TRUE, 0);
return;
}
// Side Kick
void do_side_kick( CHAR_DATA *ch, char *argument )
{
int dam;
CHAR_DATA *victim;
if(IS_NPC(ch))
return;
if ( !IS_NPC(ch) && !has_skill(ch,gsn_sidekick))
{
send_to_char("Huh?\n\r", ch );
return;
}
if ( ( victim = ch->fighting ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
if( ch->stunned )
{
send_to_char("You're still a bit woozy.\n\r",ch);
return;
}
if ( get_skill(ch,gsn_sidekick) > number_percent())
{
dam = number_range (1, ch->level);
dam += number_range(0,(ch->level)/3);
dam += number_range(0,(ch->level)/3);
dam += number_range(0,(ch->level)/3);
dam += number_range(0,(ch->level)/4);
dam += number_range(0,(ch->level)/4);
dam += number_range(0,(ch->level)/4);
dam += number_range(0,(ch->level)/4);
dam += number_range(ch->level/3,ch->level/2);
act("You kick $N brutally in the side!",ch,0,victim,TO_CHAR);
act("$n kicks you brutally in the side!",ch,0,victim,TO_VICT);
if(has_skill(ch,gsn_vital_hit))
{
if( (get_skill(ch,gsn_vital_hit) / 12) > number_percent( ))
{
check_improve(ch,gsn_vital_hit,TRUE, 3);
dam = (dam * 8) / 5;
}
}
damage(ch,victim,dam, gsn_sidekick,DAM_BASH,TRUE, 0);
check_improve(ch,gsn_sidekick,TRUE,1);
check_follow_through(ch,victim,dam);
}
else
{
damage( ch, victim, 0, gsn_sidekick,DAM_BASH,TRUE, 0);
check_improve(ch,gsn_sidekick,FALSE,1);
}
WAIT_STATE( ch, skill_table[gsn_sidekick].beats );
return;
}
// Spin Kick
void do_spin_kick( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
int dam;
int skill;
if (((get_skill(ch,gsn_spin_kick)) <= 0)
|| !has_skill(ch,gsn_spin_kick))
{
send_to_char( "Huh?\n\r", ch );
return;
}
if (!is_affected(ch,gsn_martial_arts))
{
send_to_char("You must be focused on the martial arts to use this skill.\n\r",ch);
return;
}
if ( ( victim = ch->fighting ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
if( ch->stunned )
{
send_to_char("You're still a bit woozy.\n\r",ch);
return;
}
if (number_percent() > get_skill(ch,gsn_spin_kick))
{
send_to_char("You slip and fail your kick.\n\r",ch);
check_improve(ch,gsn_spin_kick, FALSE,1);
WAIT_STATE(ch, skill_table[gsn_spin_kick].beats);
return;
}
act("You deftly spin around and kick $N in the chest!",ch,NULL,victim,TO_CHAR);
act("$n spins around and kicks you in the chest!",ch,NULL,victim,TO_VICT);
act("$n spins around deftly and kicks $N hard!",ch,NULL,victim,TO_NOTVICT);
skill = get_skill(ch,gsn_spin_kick);
if(ch->level <= 80)
dam = ch->level * 2 + (number_range(0, skill)) * 3 / 2;
else if(ch->level <= 90)
dam = ch->level * 3 + (number_range((skill/3), skill)) * 3 / 2;
else if(ch->level <= 100)
dam = ch->level * 3 + (number_range((skill/2), skill)) * 9 / 5;
else
dam = ch->level * 3 + (number_range((skill*3/4), skill)) * 9 / 4;
dam += -2*(dex_app[get_curr_stat(ch,STAT_DEX)].defensive);
if (number_percent() < get_skill(ch,gsn_spin_kick) / 8)
{
act("Your kick knocks $N's breath away!",ch,NULL,victim,TO_CHAR);
act("$n's kick knocks your breath away!",ch,NULL,victim,TO_VICT);
act("$n's kick sends $N sprawling!",ch,NULL,victim,TO_NOTVICT);
WAIT_STATE(victim,2*PULSE_VIOLENCE);
}
if(has_skill(ch,gsn_vital_hit))
{
if( (get_skill(ch,gsn_vital_hit) / 12) > number_percent( ))
{
check_improve(ch,gsn_vital_hit,TRUE, 3);
dam = (dam * 8) / 5;
}
}
WAIT_STATE(ch, skill_table[gsn_spin_kick].beats);
damage(ch,victim,dam, gsn_spin_kick,DAM_SLASH,TRUE, 0);
check_improve(ch,gsn_spin_kick, TRUE,1);
check_follow_through(ch,victim,dam);
return;
}
// Follow through
void check_follow_through(CHAR_DATA *ch, CHAR_DATA *victim, int dam)
{
int chance;
OBJ_DATA *wield;
wield = get_eq_char(ch,WEAR_WIELD);
chance = get_skill(ch,gsn_follow_through);
if (wield != NULL && IS_WEAPON_STAT(wield,WEAPON_TWO_HANDS))
{
chance=chance*(get_curr_stat(ch,STAT_DEX)/12);
}
chance=chance/2;
chance -= number_range(0,7);
if (!has_skill(ch,gsn_follow_through))
return;
if (number_percent() < chance)
{
if (ch->class == CLASS_HIGHLANDER)
{
if (wield != NULL && IS_WEAPON_STAT(wield,WEAPON_TWO_HANDS))
{
act("The momentum of $n's weapon brings them around for another attack!",ch,0,0,TO_ROOM);
act("The momentum of your swing brings your two-handed weapon around for another attack!",ch,0,0,TO_CHAR);
dam = dam * 7/4;
damage(ch, victim, dam, gsn_follow_through, DAM_SLASH, TRUE, 0);
check_improve(ch,gsn_follow_through,TRUE,2);
}
else
{
act("The momentum of $n's weapon brings them around for another attack!",ch,0,0,TO_ROOM);
act("The momentum of your swing brings your weapon around for another attack!",ch,0,0,TO_CHAR);
dam = dam * 2/3;
damage(ch, victim, dam, gsn_follow_through, DAM_SLASH, TRUE, 0);
check_improve(ch,gsn_follow_through,TRUE,2);
}
}
else if (is_affected(ch,gsn_martial_arts))
{
act("$n's leg sweeps around and strikes with a follow through!",ch,0,0,TO_ROOM);
act("Your leg sweeps around to land a follow through kick!",ch,0,0,TO_CHAR);
dam = dam * 4;
dam = dam / 5;
damage(ch, victim, dam, gsn_follow_through, DAM_BASH, TRUE, 0);
check_improve(ch,gsn_follow_through,TRUE,2);
}
}
else
check_improve(ch,gsn_follow_through,FALSE,3);
return;
}
// Blindness dust
void do_blindness_dust(CHAR_DATA *ch,char *argument)
{
CHAR_DATA *vch;
CHAR_DATA *vch_next;
AFFECT_DATA af;
int chance;
bool fighting = FALSE;
char buf[MAX_STRING_LENGTH];
if ( (chance = get_skill(ch,gsn_blindness_dust)) == 0
|| !has_skill(ch,gsn_blindness_dust))
{
send_to_char("You don't know how to make blindness dust to throw.\n\r",ch);
return;
}
if( ch->stunned )
{
send_to_char("You're still a bit woozy.\n\r",ch);
return;
}
if (ch->mana < 36)
{
send_to_char("You don't have the mana.\n\r",ch);
return;
}
if (number_percent() + 10 > chance)
{
act("$n hurls some dust into the air but it is blown away.",ch,0,0,TO_ROOM);
send_to_char("You throw out some dust but it is blown away.\n\r",ch);
ch->mana -= 18;
check_improve(ch,gsn_blindness_dust,FALSE,2);
WAIT_STATE(ch,12);
return;
}
act("$n hurls a handful of dust into the room!",ch,0,0,TO_ROOM);
send_to_char("You throw a handful of blindness dust into the room!\n\r",ch);
check_improve(ch,gsn_blindness_dust,TRUE,2);
if (ch->fighting != NULL)
fighting = TRUE;
af.where = TO_AFFECTS;
af.type = gsn_blindness_dust;
af.level = ch->level;
af.duration = (ch->level)/25;
af.bitvector = AFF_BLIND;
af.location = APPLY_HITROLL;
af.modifier = -4;
ch->mana -= 36;
WAIT_STATE(ch,12);
for (vch = ch->in_room->people; vch != NULL; vch = vch_next)
{
vch_next = vch->next_in_room;
if (is_safe_quiet(ch,vch))
continue;
if (is_same_group(ch,vch))
continue;
if (!IS_AFFECTED(vch,AFF_BLIND) && !saves_spell( ch->level,vch,DAM_OTHER))
{
act("$n appears blinded.",vch,0,0,TO_ROOM);
send_to_char("You get dust in your eyes.\n\r",vch);
affect_to_char(vch,&af);
}
if (!IS_NPC(vch) && !IS_NPC(ch) && (vch->fighting == NULL || (!fighting)))
{
sprintf(buf,"Help! %s just threw dust in my eyes!",PERS(ch,vch));
do_yell(vch,buf);
}
if (vch->fighting == NULL)
multi_hit(vch,ch,TYPE_UNDEFINED);
}
return;
}
void do_will_of_iron(CHAR_DATA *ch,char *argument)
{
AFFECT_DATA af;
// int counter;
if (((get_skill(ch,gsn_will_of_iron)) <= 0)
|| !has_skill(ch,gsn_will_of_iron) || IS_NPC(ch))
{
send_to_char( "Huh?\n\r", ch );
return;
}
if (is_affected(ch,gsn_will_of_iron))
{
send_to_char("You are already focusing your will!\n\r",ch);
return;
}
send_to_char("You focus your energy, and your will becomes strong as steel.\n\r",ch);
//check_improve(ch,gsn_will_of_iron,TRUE,1);
af.where = TO_AFFECTS;
af.type = gsn_will_of_iron;
af.level = ch->level;
af.duration = ch->level/5 + 5;
af.location = APPLY_AC;
af.modifier = -1*(ch->level*5/8);
af.bitvector = 0;
affect_to_char( ch, &af );
af.modifier = -25;
af.location = APPLY_HITROLL;
affect_to_char( ch, &af );
af.location = APPLY_REGEN;
af.modifier = 100;
affect_to_char( ch, &af );
// for(counter = 0; counter < 3250; counter++)
improve_toughness(ch);
check_improve(ch,gsn_will_of_iron,TRUE,1);
return;
}
void do_healing_trance(CHAR_DATA *ch,char *argument)
{
AFFECT_DATA af;
if (((get_skill(ch,gsn_healing_trance)) <= 0)
|| !has_skill(ch,gsn_healing_trance) || IS_NPC(ch))
{
send_to_char( "Huh?\n\r", ch );
return;
}
if (ch->fighting != NULL)
{
send_to_char("You are too busy fighting to meditate.\n\r",ch);
return;
}
if (is_affected(ch,gsn_healing_trance))
{
send_to_char("You are already at an inner peace.\n\r",ch);
return;
}
do_rest(ch,"");
send_to_char("You relax and concentrate on healing your wounds.\n\r",ch);
check_improve(ch,gsn_healing_trance,TRUE,1);
af.where = TO_AFFECTS;
af.level = ch->level;
af.type = gsn_healing_trance;
af.location = APPLY_REGEN;
af.modifier = (ch->level-1)*2.0;
af.bitvector = 0;
af.duration = 4;
affect_to_char(ch,&af);
af.location = APPLY_MANA_REGEN;
af.modifier = (ch->level-1)*.1;
affect_to_char(ch,&af);
ch->stunned = 4;
return;
}
void do_trance(CHAR_DATA *ch,char *argument)
{
AFFECT_DATA af;
if(((get_skill(ch,gsn_meditation)) <= 0)
|| !has_skill(ch,gsn_meditation) || IS_NPC(ch))
{
send_to_char( "Huh?\n\r",ch);
return;
}
if(ch->fighting != NULL)
{
send_to_char("You are too busy fighting to meditate.\n\r",ch);
return;
}
if (is_affected(ch,gsn_meditation))
{
send_to_char("You are already meditating.\n\r",ch);
return;
}
do_rest(ch,"");
send_to_char("You relax and focus your mind within.\n\r",ch);
check_improve(ch,gsn_meditation,TRUE,1);
af.where = TO_AFFECTS;
af.level = ch->level;
af.type = gsn_meditation;
af.location = APPLY_REGEN;
af.modifier = (ch->level-1)*1;
af.bitvector = 0;
af.duration = 10;
affect_to_char(ch,&af);
af.location = APPLY_MANA_REGEN;
af.modifier = (ch->level-1)*2.5;
affect_to_char(ch,&af);
//ch->stunned = 4;
return;
}
void do_purify_body(CHAR_DATA *ch,char *argument)
{
AFFECT_DATA *af;
sh_int af_type;
sh_int sn;
sn = gsn_purify_body;
if (((get_skill(ch,gsn_purify_body)) <= 0) || !has_skill(ch,gsn_purify_body) || IS_NPC(ch))
{
send_to_char( "Huh?\n\r", ch );
return;
}
if (is_affected(ch,gsn_martial_arts))
{
send_to_char( "Not while your mind focuses on the art of war.\n\r",ch);
return;
}
send_to_char("You go into a deep trance and purify your body.\n\r",ch);
check_improve(ch,gsn_purify_body,TRUE,1);
for ( af = ch->affected; af != NULL; af = af->next )
{
af_type = af->type;
if( af_type < 0 || af_type > MAX_SKILL)
{
bug("Problem: Monk :: Purify Body :: Affect remove",0);
return;
}
if( af_type != gsn_healing_trance
&& skill_table[af_type].slot != 999 )
check_dispel(ch->level+35,ch,af->type);
}
do_sleep(ch,"");
ch->stunned = 2;
WAIT_STATE(ch,24);
return;
}
/*void do_spinkick(CHAR_DATA *ch, char *argument)
{
ROOM_INDEX_DATA *was_in;
CHAR_DATA *victim,*vch,*vch_next;
int attempt, chance, dam, level;
char arg1[MAX_INPUT_LENGTH];
char buf[MAX_INPUT_LENGTH];
one_argument(argument,arg1);
if(IS_NPC(ch))
return;
if ( (chance = get_skill(ch,gsn_spinkick)) == 0
|| !has_skill(ch,gsn_spinkick))
{
send_to_char("Huh?\n\r",ch);
return;
}
if(ch->fighting != NULL)
victim = ch->fighting;
else
{
if( (victim = get_char_room(ch,arg1)) == NULL )
{
send_to_char("They're not here.\n\r",ch);
return;
}
}
if(victim == ch)
{
send_to_char("Kicking yourself? get real.\n\r",ch);
return;
}
if (!IS_NPC(victim) && !can_pkill(ch,victim)) {
send_to_char("You can't seem to kick them.",ch);
return;
}
if (IS_AFFECTED(ch,AFF_FEAR) && (number_percent() <= 25)) {
act("You attempt to spin kick, but begin crying instead.",ch,NULL,NULL,TO_CHAR);
act("$n attempts to spin kick, but begins crying instead.",ch,NULL,NULL,TO_ROOM);
WAIT_STATE(ch,DEF_FEAR_WAIT);
return; }
if(ch->stunned)
{
send_to_char("You are still a bit woozy.\n\r",ch);
return;
}
level = ch->level + 5;
// chance = (ch->level - victim->level) * 2;
chance += number_range(20,50);
chance -= get_curr_stat(victim,STAT_DEX)/2;
chance -= get_curr_stat(victim,STAT_STR)/3;
chance += get_curr_stat(ch,STAT_STR)/3;
chance += get_curr_stat(ch,STAT_DEX);
if (IS_AFFECTED(victim,AFF_HASTE))
chance -= 30;
if (IS_AFFECTED(ch,AFF_HASTE))
chance += 25;
if (IS_AFFECTED(victim,AFF_SLOW))
chance += 20;
if (IS_AFFECTED(ch,AFF_SLOW))
chance -= 30;
if (IS_AFFECTED(victim,AFF_FLYING))
chance += 5;
chance += (ch->size - victim->size)*10;
if (!IS_NPC(victim) && !IS_NPC(ch) && (victim->hit > 1))
{
sprintf(buf,"Help! %s just tried to kick me out of the room!",PERS(ch,victim));
if(ch->fighting == NULL)
{
do_yell(victim,buf);
}
}
if (number_percent() > chance)
{
act("You spin your leg around but miss $N.",ch,0,victim,TO_CHAR);
act("$n spins his leg around but misses you.",ch,0,victim,TO_VICT);
act("$n spins his leg visciously at $N but misses.",ch,0,victim,TO_NOTVICT);
check_improve(ch,gsn_spinkick,FALSE,3);
WAIT_STATE(ch,10);
if(victim->fighting == NULL)
multi_hit(victim,ch,TYPE_UNDEFINED);
return;
}
was_in = victim->in_room;
dam = dice(level,8);
// Stance modifier
if (!IS_NPC(ch) && ch->stance[0] > 0 && number_percent() < 3)
{
int stance = ch->stance[0];
if (ch->stance[stance] >= 200)
dam += dice(ch->stance[stance],2);
else if(ch->stance[stance] > 0)
dam += dice(ch->stance[stance],1);
}
if(number_percent() < 25)
{
for ( attempt = 0; attempt < 6; attempt++ )
{
EXIT_DATA *pexit;
int door;
char dir[MAX_STRING_LENGTH/4];
door = number_door( );
if (door == 0)
(strcpy(dir,"north"));
else if (door == 1)
(strcpy(dir,"east"));
else if (door == 2)
(strcpy(dir,"south"));
else if (door == 3)
(strcpy(dir,"west"));
else if (door == 4)
(strcpy(dir,"up"));
else if (door == 5)
(strcpy(dir,"down"));
else
strcpy(dir,"none");
if ( ( pexit = was_in->exit[door] ) == 0
|| pexit->u1.to_room == NULL
|| ( IS_SET(pexit->exit_info, EX_CLOSED) )
|| ( IS_NPC(victim)
&& IS_SET(pexit->u1.to_room->room_flags, ROOM_NO_MOB) ) )
continue;
if ( ( was_in->sector_type == SECT_AIR)
|| ( (pexit->u1.to_room->sector_type == SECT_AIR )
&& ( !IS_AFFECTED(victim, AFF_FLYING) ) ) )
continue;
if (IS_SET(pexit->exit_info,EX_CLOSED))
{
act("You spin around and kick $N through the door with incredible force!",ch,0,victim,TO_CHAR);
act("$n's spin kick sends $N crashing through the door with incredible force!",ch,0,victim,TO_NOTVICT);
act("$n spins around and kicks you through the door with incredible force!",ch,0,victim,TO_VICT);
}
else
{
act("You spin your leg visciously at $N and kick $M from the room!",ch,0,victim,TO_CHAR);
act("$n spins his leg visciously at $N and kicks $M from the room!",ch,NULL,victim,TO_NOTVICT);
act("$n spins his leg visciously at you and kicks you from the room!",ch,0,victim,TO_VICT);
dam = dice(level,5);
}
for(vch = victim->in_room->people; vch != NULL; vch = vch_next)
{
vch_next = vch->next_in_room;
if(IS_IMMORTAL(vch))
{
sprintf(buf,"\n\r%s is kicked %s.",victim->name,dir);
send_to_char(buf,vch);
}
}
char_from_room(victim);
char_to_room(victim, pexit->u1.to_room);
do_look(victim,"auto");
if (IS_SET(pexit->exit_info,EX_CLOSED))
{
REMOVE_BIT(pexit->exit_info,EX_CLOSED);
act("With a deafening crash the door explodes open and $n comes flying into the room!",victim,0,0,TO_ROOM);
}
else
{
act("$n comes flying into the room with incredible force!",victim,0,0,TO_ROOM);
}
if (saves_spell(ch->level,victim,DAM_BASH))
dam /= 2;
damage(ch,victim,dam,gsn_spinkick,DAM_BASH,TRUE,0);
WAIT_STATE(victim,36);
WAIT_STATE(ch,24);
stop_fighting( ch, TRUE );
return;
}
if( attempt == 6 )
{
dam += dice(level,4);
act("You spin your leg viscously at $N and kick $M brutally into a wall!",ch,0,victim,TO_CHAR);
act("$n spins his leg viscously at $N and kicks $M brutally into a wall!",ch,0,victim,TO_NOTVICT);
act("$n spins his leg viscously at you and kicks you brutally into a wall!",ch,0,victim,TO_VICT);
if (saves_spell(ch->level,victim,DAM_BASH))
dam /= 2;
damage(ch,victim,dam,gsn_spinkick,DAM_BASH,TRUE,0);
WAIT_STATE(ch,24);
WAIT_STATE(victim,24);
}
}
else
{
act("You spin your leg viscously at $N and kick $M brutally!",ch,0,victim,TO_CHAR);
act("$n spins his leg viscously at $N and kicks $M brutally!",ch,0,victim,TO_NOTVICT);
act("$n spins his leg viscously at you and kicks you brutally!",ch,0,victim,TO_VICT);
if (saves_spell(ch->level-4,victim,DAM_BASH))
dam /= 2;
damage(ch,victim,dam,gsn_spinkick,DAM_BASH,TRUE,0);
if(number_range(1,2) == 2)
WAIT_STATE(victim,24);
else
WAIT_STATE(victim,12);
WAIT_STATE(ch,12);
}
return;
}*/
/*void do_chop( CHAR_DATA *ch, char *argument)
{
CHAR_DATA *victim;
int chance, dam;
char arg[MAX_INPUT_LENGTH];
OBJ_DATA *wield,*second;
int multiplier;
bool DUAL = FALSE;
dam = 0;
one_argument(argument,arg);
if ((chance = get_skill(ch,gsn_chop) ) == 0
|| !has_skill(ch,gsn_chop) )
{
send_to_char("Chopping? What's that?\n\r",ch);
return;
}
if (arg[0] == '\0')
{
victim = ch->fighting;
if (victim == NULL)
{
send_to_char("But you aren't fighting anyone!\n\r",ch);
return;
}
}
else 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("You can't chop at yourself!\n\r",ch);
return;
}
if (IS_AFFECTED(ch,AFF_FEAR) && (number_percent() <= 25)) {
act("You attempt to chop, but begin crying instead.",ch,NULL,NULL,TO_CHAR);
act("$n attempts to chop, but begins crying instead.",ch,NULL,NULL,TO_ROOM);
WAIT_STATE(ch,DEF_FEAR_WAIT);
return; }
if(ch->stunned)
{
send_to_char("You are still a bit woozy.\n\r",ch);
return;
}
wield = get_eq_char(ch,WEAR_WIELD);
second = get_eq_char(ch,WEAR_SECONDARY);
if ((wield == NULL)
|| (( wield->value[0] != WEAPON_SWORD)
&& ( wield->value[0] != WEAPON_AXE)
&& ( wield->value[0] != WEAPON_DAGGER) ))
{
if ((second == NULL)
|| (( second->value[0] != WEAPON_SWORD)
&& ( second->value[0] != WEAPON_AXE)
&& ( second->value[0] != WEAPON_DAGGER) ))
{
send_to_char("You must be wielding a sword or axe to chop.\n\r",ch);
return;
}
else
{
DUAL = TRUE;
}
}
if (is_safe(ch,victim) )
return;
chance += ch->carry_weight/25;
chance -= victim->carry_weight/20;
chance += (ch->size - victim->size)*20;
chance -= get_curr_stat(victim,STAT_DEX);
chance += get_curr_stat(ch,STAT_STR)/3;
chance += get_curr_stat(ch,STAT_DEX)/2;
if (IS_AFFECTED(ch,AFF_HASTE) )
chance += 10;
if (IS_AFFECTED(victim,AFF_HASTE) )
chance -= 10;
chance += (ch->level - victim->level);
act("$n attempts to split open $N with a quick chop!",ch,0,victim,TO_NOTVICT);
act("You attempt to split open $N with a quick chop!",ch,0,victim,TO_CHAR);
act("$n attempts to split you open with a quick chop!",ch,0,victim,TO_VICT);
if (number_percent() < chance)
{
check_improve(ch,gsn_lunge,TRUE,1);
WAIT_STATE(ch,skill_table[gsn_chop].beats);
if(DUAL)
wield = second;
if (wield->pIndexData->new_format)
dam = dice(wield->value[1],wield->value[2]);
else
dam = number_range(wield->value[1],wield->value[2]);
if (get_skill(ch,gsn_enhanced_damage) > 0 )
{
if (number_percent() <= get_skill(ch,gsn_enhanced_damage) )
{
check_improve(ch,gsn_enhanced_damage,TRUE,1);
dam += dam * (number_range(50,100)/100) * ch->pcdata->learned[gsn_enhanced_damage]/100;
}
}
dam += GET_DAMROLL(ch);
dam *= ch->pcdata->learned[gsn_chop];
dam /= 100;
multiplier = number_range(ch->level/8, ch->level/4);
multiplier /= 10;
multiplier += 5/4;
dam *= multiplier;
if(!DUAL && IS_WEAPON_STAT(wield,WEAPON_TWO_HANDS))
dam *= 1.5;
if (dam <= 0)
dam = 1;
damage(ch,victim,dam,gsn_chop,DAM_PIERCE,TRUE,0);
}
else
{
damage(ch,victim,dam,gsn_chop,DAM_PIERCE,TRUE,0);
check_improve(ch,gsn_chop,FALSE,1);
WAIT_STATE(ch,skill_table[gsn_chop].beats);
}
return;
}
*/