/****************************************************************************
* _______ _ ______ _______ _______ ______ *
* ( ____ \( \ ( __ \ |\ /|( ___ )( )|\ /|( __ \ *
* | ( \/| ( | ( \ )| ) ( || ( ) || () () || ) ( || ( \ ) *
* | (__ | | | | ) || (___) || (___) || || || || | | || | ) | *
* | __) | | | | | || ___ || ___ || |(_)| || | | || | | | *
* | ( | | | | ) || ( ) || ( ) || | | || | | || | ) | *
* | (____/\| (____/\| (__/ )| ) ( || ) ( || ) ( || (___) || (__/ ) *
* (_______/(_______/(______/ |/ \||/ \||/ \|(_______)(______/ *
* +-+-+-+ +-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+ *
* |T|h|e| |O|a|k|l|a|n|d| |C|h|r|o|n|i|c|l|e|s| *
* +-+-+-+ +-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+ *
* ------------------------------------------------------------------------- *
* EldhaMUD code (C) 2003-2005 by Robert Powell (Tommi) *
* EldhaMUD Team: Celest, Altere and Krelowyn *
* ------------------------------------------------------------------------- *
* *
****************************************************************************/
/****************************************************************************
* [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// *
* -----------------------------------------------------------| (0...0) *
* SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by Derek Snider | ).:.( *
* -----------------------------------------------------------| {o o} *
* SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ *
* Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek, |~'~.VxvxV.~'~*
* Tricops and Fireblade | *
* ------------------------------------------------------------------------ *
* Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* ------------------------------------------------------------------------ *
* Player skills module *
****************************************************************************/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "./Headers/mud.h"
extern int get_secflag( char *flag );
ch_ret spell_attack( int, int, CHAR_DATA *, void * );
char *const spell_flag[] =
{ "water", "earth", "air", "astral", "area", "distant", "reverse",
"noself", "_unused2_", "accumulative", "recastable", "noscribe",
"nobrew", "group", "object", "character", "secretskill", "pksensitive",
"stoponfail", "nofight", "nodispel", "randomtarget", "r2", "r3", "r4",
"r5", "r6", "r7", "r8", "r9", "r10", "r11"
};
char *const spell_saves[] =
{ "none", "poison_death", "wands", "para_petri", "breath", "spell_staff"
};
char *const spell_save_effect[] =
{ "none", "negate", "eightdam", "quarterdam", "halfdam", "3qtrdam",
"reflect", "absorb"
};
char *const spell_damage[] =
{ "none", "fire", "cold", "electricity", "energy", "acid", "poison", "drain"
};
char *const spell_action[] =
{ "none", "create", "destroy", "resist", "suscept", "divinate", "obscure",
"change"
};
char *const spell_power[] =
{ "none", "minor", "greater", "major"
};
char *const spell_class[] =
{ "none", "lunar", "solar", "travel", "summon", "life", "death", "illusion"
};
char *const target_type[] =
{ "ignore", "offensive", "defensive", "self", "objinv"
};
void show_char_to_char( CHAR_DATA * list, CHAR_DATA * ch );
int ris_save( CHAR_DATA * ch, int schance, int ris );
bool check_illegal_psteal( CHAR_DATA * ch, CHAR_DATA * victim );
/* from magic.c */
void failed_casting( struct skill_type *skill, CHAR_DATA * ch, CHAR_DATA * victim, OBJ_DATA * obj );
/*
* Dummy function
*/
void skill_notfound( CHAR_DATA * ch, char *argument )
{
send_to_char( "Huh?\n\r", ch );
return;
}
int get_ssave( char *name )
{
int x;
for( x = 0; x < sizeof( spell_saves ) / sizeof( spell_saves[0] ); x++ )
if( !str_cmp( name, spell_saves[x] ) )
return x;
return -1;
}
int get_starget( char *name )
{
int x;
for( x = 0; x < sizeof( target_type ) / sizeof( target_type[0] ); x++ )
if( !str_cmp( name, target_type[x] ) )
return x;
return -1;
}
int get_sflag( char *name )
{
int x;
for( x = 0; x < sizeof( spell_flag ) / sizeof( spell_flag[0] ); x++ )
if( !str_cmp( name, spell_flag[x] ) )
return x;
return -1;
}
int get_sdamage( char *name )
{
int x;
for( x = 0; x < sizeof( spell_damage ) / sizeof( spell_damage[0] ); x++ )
if( !str_cmp( name, spell_damage[x] ) )
return x;
return -1;
}
int get_saction( char *name )
{
int x;
for( x = 0; x < sizeof( spell_action ) / sizeof( spell_action[0] ); x++ )
if( !str_cmp( name, spell_action[x] ) )
return x;
return -1;
}
int get_ssave_effect( char *name )
{
int x;
for( x = 0; x < sizeof( spell_save_effect ) / sizeof( spell_save_effect[0] ); x++ )
if( !str_cmp( name, spell_save_effect[x] ) )
return x;
return -1;
}
int get_spower( char *name )
{
int x;
for( x = 0; x < sizeof( spell_power ) / sizeof( spell_power[0] ); x++ )
if( !str_cmp( name, spell_power[x] ) )
return x;
return -1;
}
int get_sclass( char *name )
{
int x;
for( x = 0; x < sizeof( spell_class ) / sizeof( spell_class[0] ); x++ )
if( !str_cmp( name, spell_class[x] ) )
return x;
return -1;
}
bool is_legal_kill( CHAR_DATA * ch, CHAR_DATA * vch )
{
if( IS_NPC( ch ) || IS_NPC( vch ) )
return TRUE;
if( !IS_PKILL( ch ) || !IS_PKILL( vch ) )
return FALSE;
if( ch->pcdata->clan && ch->pcdata->clan == vch->pcdata->clan )
return FALSE;
return TRUE;
}
/*
* Perform a binary search on a section of the skill table
* Each different section of the skill table is sorted alphabetically
* Only match skills player knows -Thoric
*/
bool check_skill( CHAR_DATA * ch, char *command, char *argument )
{
int sn;
int first = gsn_first_skill;
int top = gsn_first_weapon - 1;
int mana, blood;
struct timeval time_used;
/*
* bsearch for the skill
*/
for( ;; )
{
sn = ( first + top ) >> 1;
if( LOWER( command[0] ) == LOWER( skill_table[sn]->name[0] )
&& !str_prefix( command, skill_table[sn]->name )
&& ( skill_table[sn]->skill_fun || skill_table[sn]->spell_fun != spell_null ) && ( can_use_skill( ch, 0, sn ) ) )
/*
* && (IS_NPC(ch)
* || (ch->pcdata->learned[sn] > 0
* && ch->level >= skill_table[sn]->skill_level[ch->class])) )
*/
break;
if( first >= top )
return FALSE;
if( strcmp( command, skill_table[sn]->name ) < 1 )
top = sn - 1;
else
first = sn + 1;
}
if( !check_pos( ch, skill_table[sn]->minimum_position ) )
return TRUE;
if( IS_NPC( ch ) && ( IS_AFFECTED( ch, AFF_CHARM ) || IS_AFFECTED( ch, AFF_POSSESS ) ) )
{
send_to_char( "For some reason, you seem unable to perform that...\n\r", ch );
act( AT_GREY, "$n wanders around aimlessly.", ch, NULL, NULL, TO_ROOM );
return TRUE;
}
/*
* check if mana is required
*/
if( skill_table[sn]->min_mana )
{
mana = IS_NPC( ch ) ? 0 : UMAX( skill_table[sn]->min_mana,
100 / ( 2 + ch->level - skill_table[sn]->skill_level[ch->class] ) );
blood = UMAX( 1, ( mana + 4 ) / 8 ); /* NPCs don't have PCDatas. -- Altrag */
if( IS_VAMPIRE( ch ) )
{
if( ch->pcdata->condition[COND_BLOODTHIRST] < blood )
{
send_to_char( "You don't have enough blood power.\n\r", ch );
return TRUE;
}
}
else if( !IS_NPC( ch ) && ch->mana < mana )
{
send_to_char( "You don't have enough mana.\n\r", ch );
return TRUE;
}
}
else
{
mana = 0;
blood = 0;
}
/*
* Is this a real do-fun, or a really a spell?
*/
if( !skill_table[sn]->skill_fun )
{
ch_ret retcode = rNONE;
void *vo = NULL;
CHAR_DATA *victim = NULL;
OBJ_DATA *obj = NULL;
target_name = "";
switch ( skill_table[sn]->target )
{
default:
bug( "Check_skill: bad target for sn %d.", sn );
send_to_char( "Something went wrong...\n\r", ch );
return TRUE;
case TAR_IGNORE:
vo = NULL;
if( argument[0] == '\0' )
{
if( ( victim = who_fighting( ch ) ) != NULL )
target_name = victim->name;
}
else
target_name = argument;
break;
case TAR_CHAR_OFFENSIVE:
{
if( argument[0] == '\0' && ( victim = who_fighting( ch ) ) == NULL )
{
ch_printf( ch, "Confusion overcomes you as your '%s' has no target.\n\r", skill_table[sn]->name );
return TRUE;
}
else if( argument[0] != '\0' && ( victim = get_char_room( ch, argument ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return TRUE;
}
}
if( is_safe( ch, victim, TRUE ) )
return TRUE;
if( ch == victim && SPELL_FLAG( skill_table[sn], SF_NOSELF ) )
{
send_to_char( "You can't target yourself!\n\r", ch );
return TRUE;
}
if( !IS_NPC( ch ) )
{
if( !IS_NPC( victim ) )
{
/*
* Sheesh! can't do anything
* send_to_char( "You can't do that on a player.\n\r", ch );
* return TRUE;
*/
/*
* if ( xIS_SET(victim->act, PLR_PK))
*/
if( get_timer( ch, TIMER_PKILLED ) > 0 )
{
send_to_char( "You have been killed in the last 5 minutes.\n\r", ch );
return TRUE;
}
if( get_timer( victim, TIMER_PKILLED ) > 0 )
{
send_to_char( "This player has been killed in the last 5 minutes.\n\r", ch );
return TRUE;
}
if( victim != ch )
send_to_char( "You really shouldn't do this to another player...\n\r", ch );
}
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 TRUE;
}
}
check_illegal_pk( ch, victim );
vo = ( void * )victim;
break;
case TAR_CHAR_DEFENSIVE:
{
if( argument[0] != '\0' && ( victim = get_char_room( ch, argument ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return TRUE;
}
if( !victim )
victim = ch;
}
if( ch == victim && SPELL_FLAG( skill_table[sn], SF_NOSELF ) )
{
send_to_char( "You can't target yourself!\n\r", ch );
return TRUE;
}
vo = ( void * )victim;
break;
case TAR_CHAR_SELF:
victim = ch;
break;
case TAR_OBJ_INV:
{
if( ( obj = get_obj_carry( ch, argument ) ) == NULL )
{
send_to_char( "You can't find that.\n\r", ch );
return TRUE;
}
}
vo = ( void * )obj;
break;
}
/*
* waitstate
*/
WAIT_STATE( ch, skill_table[sn]->beats );
/*
* check for failure
*/
if( ( number_percent( ) + skill_table[sn]->difficulty * 5 ) > ( IS_NPC( ch ) ? 75 : LEARNED( ch, sn ) ) )
{
failed_casting( skill_table[sn], ch, victim, obj );
learn_from_failure( ch, sn );
if( mana )
{
if( IS_VAMPIRE( ch ) )
gain_condition( ch, COND_BLOODTHIRST, -blood / 2 );
else
ch->mana -= mana / 2;
}
return TRUE;
}
if( mana )
{
if( IS_VAMPIRE( ch ) )
gain_condition( ch, COND_BLOODTHIRST, -blood );
else
ch->mana -= mana;
}
start_timer( &time_used );
retcode = ( *skill_table[sn]->spell_fun ) ( sn, ch->level, ch, vo );
end_timer( &time_used );
update_userec( &time_used, &skill_table[sn]->userec );
if( retcode == rCHAR_DIED || retcode == rERROR )
return TRUE;
if( char_died( ch ) )
return TRUE;
if( retcode == rSPELL_FAILED )
{
learn_from_failure( ch, sn );
retcode = rNONE;
}
else
learn_from_success( ch, sn );
if( skill_table[sn]->target == TAR_CHAR_OFFENSIVE && victim != ch && !char_died( victim ) )
{
CHAR_DATA *vch;
CHAR_DATA *vch_next;
for( vch = ch->in_room->first_person; vch; vch = vch_next )
{
vch_next = vch->next_in_room;
if( victim == vch && !victim->fighting && victim->master != ch )
{
retcode = multi_hit( victim, ch, TYPE_UNDEFINED );
break;
}
}
}
return TRUE;
}
if( mana )
{
if( IS_VAMPIRE( ch ) )
gain_condition( ch, COND_BLOODTHIRST, -blood );
else
ch->mana -= mana;
}
ch->prev_cmd = ch->last_cmd; /* haus, for automapping */
ch->last_cmd = skill_table[sn]->skill_fun;
start_timer( &time_used );
( *skill_table[sn]->skill_fun ) ( ch, argument );
end_timer( &time_used );
update_userec( &time_used, &skill_table[sn]->userec );
tail_chain( );
return TRUE;
}
void do_skin( CHAR_DATA * ch, char *argument )
{
OBJ_DATA *korps;
OBJ_DATA *corpse;
OBJ_DATA *obj;
OBJ_DATA *skin;
bool found;
char *name;
char buf[MAX_STRING_LENGTH];
found = FALSE;
if( !IS_PKILL( ch ) && !IS_IMMORTAL( ch ) )
{
send_to_char( "Leave the hideous defilings to the killers!\n", ch );
return;
}
if( argument[0] == '\0' )
{
send_to_char( "Whose corpse do you wish to skin?\n\r", ch );
return;
}
if( ( corpse = get_obj_here( ch, argument ) ) == NULL )
{
send_to_char( "You cannot find that here.\n\r", ch );
return;
}
if( ( obj = get_eq_char( ch, WEAR_WIELD ) ) == NULL )
{
send_to_char( "You have no weapon with which to perform this deed.\n\r", ch );
return;
}
if( corpse->item_type != ITEM_CORPSE_NPC )
{
send_to_char( "You can only skin the bodies of player characters.\n\r", ch );
return;
}
/*
* if ( obj->value[3] != 1
* && obj->value[3] != 2
* && obj->value[3] != 3
* && obj->value[3] != 11 )
* {
* send_to_char( "There is nothing you can do with this corpse.\n\r", ch );
* return;
* }
*/
if( get_obj_index( OBJ_VNUM_SKIN ) == NULL )
{
bug( "Vnum 23 (OBJ_VNUM_SKIN) not found for do_skin!", 0 );
return;
}
korps = create_object( get_obj_index( OBJ_VNUM_CORPSE_PC ), 0 );
skin = create_object( get_obj_index( OBJ_VNUM_SKIN ), 0 );
name = IS_NPC( ch ) ? korps->short_descr : corpse->short_descr;
sprintf( buf, skin->short_descr, name );
STRFREE( skin->short_descr );
skin->short_descr = STRALLOC( buf );
sprintf( buf, skin->description, name );
STRFREE( skin->description );
skin->description = STRALLOC( buf );
act( AT_BLOOD, "$n strips the skin from $p.", ch, corpse, NULL, TO_ROOM );
act( AT_BLOOD, "You strip the skin from $p.", ch, corpse, NULL, TO_CHAR );
/*
* act( AT_MAGIC, "\nThe skinless corpse is dragged through the ground by a strange force...", ch, corpse, NULL, TO_CHAR);
* act( AT_MAGIC, "\nThe skinless corpse is dragged through the ground by a strange force...", ch, corpse, NULL, TO_ROOM);
*/
extract_obj( corpse );
obj_to_char( skin, ch );
return;
}
/*
* Lookup a skills information
* High god command
*/
void do_slookup( CHAR_DATA * ch, char *argument )
{
char buf[MAX_STRING_LENGTH];
char arg[MAX_INPUT_LENGTH];
int sn;
int iClass, iRace;
SKILLTYPE *skill = NULL;
one_argument( argument, arg );
if( arg[0] == '\0' )
{
send_to_char( "Slookup what?\n\r", ch );
return;
}
if( !str_cmp( arg, "all" ) )
{
for( sn = 0; sn < top_sn && skill_table[sn] && skill_table[sn]->name; sn++ )
pager_printf( ch, "Sn: %4d Slot: %4d Skill/spell: '%-20s' Damtype: %s\n\r",
sn, skill_table[sn]->slot, skill_table[sn]->name, spell_damage[SPELL_DAMAGE( skill_table[sn] )] );
}
else if( !str_cmp( arg, "herbs" ) )
{
for( sn = 0; sn < top_herb && herb_table[sn] && herb_table[sn]->name; sn++ )
pager_printf( ch, "%d) %s\n\r", sn, herb_table[sn]->name );
}
else
{
SMAUG_AFF *aff;
int cnt = 0;
if( arg[0] == 'h' && is_number( arg + 1 ) )
{
sn = atoi( arg + 1 );
if( !IS_VALID_HERB( sn ) )
{
send_to_char( "Invalid herb.\n\r", ch );
return;
}
skill = herb_table[sn];
}
else if( is_number( arg ) )
{
sn = atoi( arg );
if( ( skill = get_skilltype( sn ) ) == NULL )
{
send_to_char( "Invalid sn.\n\r", ch );
return;
}
sn %= 1000;
}
else if( ( sn = skill_lookup( arg ) ) >= 0 )
skill = skill_table[sn];
else if( ( sn = herb_lookup( arg ) ) >= 0 )
skill = herb_table[sn];
else
{
send_to_char( "No such skill, spell, proficiency or tongue.\n\r", ch );
return;
}
if( !skill )
{
send_to_char( "Not created yet.\n\r", ch );
return;
}
ch_printf( ch, "Sn: %4d Slot: %4d %s: '%-20s'\n\r", sn, skill->slot, skill_tname[skill->type], skill->name );
if( skill->info )
ch_printf( ch, "DamType: %s ActType: %s ClassType: %s PowerType: %s\n\r",
spell_damage[SPELL_DAMAGE( skill )],
spell_action[SPELL_ACTION( skill )],
spell_class[SPELL_CLASS( skill )], spell_power[SPELL_POWER( skill )] );
if( skill->flags )
{
int x;
strcpy( buf, "Flags:" );
for( x = 0; x < 32; x++ )
if( SPELL_FLAG( skill, 1 << x ) )
{
strcat( buf, " " );
strcat( buf, spell_flag[x] );
}
strcat( buf, "\n\r" );
send_to_char( buf, ch );
}
ch_printf( ch, "Saves: %s SaveEffect: %s\n\r",
spell_saves[( int )skill->saves], spell_save_effect[SPELL_SAVE( skill )] );
if( skill->difficulty != '\0' )
ch_printf( ch, "Difficulty: %d\n\r", ( int )skill->difficulty );
ch_printf( ch, "Type: %s Target: %s Minpos: %d Mana: %d Beats: %d Range: %d\n\r",
skill_tname[skill->type],
target_type[URANGE( TAR_IGNORE, skill->target, TAR_OBJ_INV )],
skill->minimum_position, skill->min_mana, skill->beats, skill->range );
ch_printf( ch, "Flags: %d Guild: %d Value: %d Info: %d Code: %s\n\r",
skill->flags,
skill->guild, skill->value, skill->info, skill->skill_fun ? skill->skill_fun_name : skill->spell_fun_name );
ch_printf( ch, "Difficulty: %d \n\r", skill->difficulty);
ch_printf( ch, "Sectors Allowed: %s\n", skill->spell_sector ? flag_string( skill->spell_sector, sec_flags ) : "All" );
ch_printf( ch, "Dammsg: %s\n\rWearoff: %s\n", skill->noun_damage, skill->msg_off ? skill->msg_off : "(none set)" );
if( skill->dice && skill->dice[0] != '\0' )
ch_printf( ch, "Dice: %s\n\r", skill->dice );
if( skill->teachers && skill->teachers[0] != '\0' )
ch_printf( ch, "Teachers: %s\n\r", skill->teachers );
if( skill->components && skill->components[0] != '\0' )
ch_printf( ch, "Components: %s\n\r", skill->components );
if( skill->participants )
ch_printf( ch, "Participants: %d\n\r", ( int )skill->participants );
if( skill->userec.num_uses )
send_timer( &skill->userec, ch );
for( aff = skill->affects; aff; aff = aff->next )
{
if( aff == skill->affects )
send_to_char( "\n\r", ch );
sprintf( buf, "Affect %d", ++cnt );
if( aff->location )
{
strcat( buf, " modifies " );
strcat( buf, a_types[aff->location % REVERSE_APPLY] );
strcat( buf, " by '" );
strcat( buf, aff->modifier );
if( aff->bitvector != -1 )
strcat( buf, "' and" );
else
strcat( buf, "'" );
}
if( aff->bitvector != -1 )
{
strcat( buf, " applies " );
strcat( buf, a_flags[aff->bitvector] );
}
if( aff->duration[0] != '\0' && aff->duration[0] != '0' )
{
strcat( buf, " for '" );
strcat( buf, aff->duration );
strcat( buf, "' rounds" );
}
if( aff->location >= REVERSE_APPLY )
strcat( buf, " (affects caster only)" );
strcat( buf, "\n\r" );
send_to_char( buf, ch );
if( !aff->next )
send_to_char( "\n\r", ch );
}
if( skill->hit_char && skill->hit_char[0] != '\0' )
ch_printf( ch, "Hitchar : %s\n\r", skill->hit_char );
if( skill->hit_vict && skill->hit_vict[0] != '\0' )
ch_printf( ch, "Hitvict : %s\n\r", skill->hit_vict );
if( skill->hit_room && skill->hit_room[0] != '\0' )
ch_printf( ch, "Hitroom : %s\n\r", skill->hit_room );
if( skill->hit_dest && skill->hit_dest[0] != '\0' )
ch_printf( ch, "Hitdest : %s\n\r", skill->hit_dest );
if( skill->miss_char && skill->miss_char[0] != '\0' )
ch_printf( ch, "Misschar : %s\n\r", skill->miss_char );
if( skill->miss_vict && skill->miss_vict[0] != '\0' )
ch_printf( ch, "Missvict : %s\n\r", skill->miss_vict );
if( skill->miss_room && skill->miss_room[0] != '\0' )
ch_printf( ch, "Missroom : %s\n\r", skill->miss_room );
if( skill->die_char && skill->die_char[0] != '\0' )
ch_printf( ch, "Diechar : %s\n\r", skill->die_char );
if( skill->die_vict && skill->die_vict[0] != '\0' )
ch_printf( ch, "Dievict : %s\n\r", skill->die_vict );
if( skill->die_room && skill->die_room[0] != '\0' )
ch_printf( ch, "Dieroom : %s\n\r", skill->die_room );
if( skill->imm_char && skill->imm_char[0] != '\0' )
ch_printf( ch, "Immchar : %s\n\r", skill->imm_char );
if( skill->imm_vict && skill->imm_vict[0] != '\0' )
ch_printf( ch, "Immvict : %s\n\r", skill->imm_vict );
if( skill->imm_room && skill->imm_room[0] != '\0' )
ch_printf( ch, "Immroom : %s\n\r", skill->imm_room );
if( skill->type != SKILL_HERB )
{
if( skill->type != SKILL_RACIAL )
{
send_to_char( "--------------------------[CLASS USE]--------------------------\n\r", ch );
for( iClass = 0; iClass < MAX_PC_CLASS; iClass++ )
{
strcpy( buf, class_table[iClass]->who_name );
sprintf( buf + 3, ") lvl: %3d max: %2d%%", skill->skill_level[iClass], skill->skill_adept[iClass] );
if( iClass % 3 == 2 )
strcat( buf, "\n\r" );
else
strcat( buf, " " );
send_to_char( buf, ch );
}
}
else
{
send_to_char( "\n\r--------------------------[RACE USE]--------------------------\n\r", ch );
for( iRace = 0; iRace < MAX_PC_RACE; iRace++ )
{
sprintf( buf, "%8.8s) lvl: %3d max: %2d%%",
race_table[iRace]->race_name, skill->race_level[iRace], skill->race_adept[iRace] );
if( !strcmp( race_table[iRace]->race_name, "unused" ) )
sprintf( buf, " " );
if( ( iRace > 0 ) && ( iRace % 2 == 1 ) )
strcat( buf, "\n\r" );
else
strcat( buf, " " );
send_to_char( buf, ch );
}
}
}
send_to_char( "\n\r", ch );
}
return;
}
/*
* Set a skill's attributes or what skills a player has.
* High god command, with support for creating skills/spells/herbs/etc
*/
void do_sset( CHAR_DATA * ch, char *argument )
{
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
int value;
int sn, i;
bool fAll;
argument = one_argument( argument, arg1 );
argument = one_argument( argument, arg2 );
if( arg1[0] == '\0' || arg2[0] == '\0' || argument[0] == '\0' )
{
send_to_char( "Syntax: sset <victim> <skill> <value>\n\r", ch );
send_to_char( "or: sset <victim> all <value>\n\r", ch );
if( get_trust( ch ) > LEVEL_SUB_IMPLEM )
{
send_to_char( "or: sset save skill table\n\r", ch );
send_to_char( "or: sset save herb table\n\r", ch );
send_to_char( "or: sset create skill 'new skill'\n\r", ch );
send_to_char( "or: sset create herb 'new herb'\n\r", ch );
send_to_char( "or: sset create ability 'new ability'\n\r", ch );
}
if( get_trust( ch ) > LEVEL_GREATER )
{
send_to_char( "or: sset <sn> <field> <value>\n\r", ch );
send_to_char( "\n\rField being one of:\n\r", ch );
send_to_char( " name code target minpos slot mana beats dammsg wearoff guild minlevel\n\r", ch );
send_to_char( " type damtype acttype classtype powertype seffect flag dice value difficulty\n\r", ch );
send_to_char( " affect rmaffect level adept hit miss die imm (char/vict/room)\n\r", ch );
send_to_char( " components teachers racelevel raceadept\n\r", ch );
send_to_char( " sector\n\r", ch );
send_to_char( "Affect having the fields: <location> <modfifier> [duration] [bitvector]\n\r", ch );
send_to_char( "(See AFFECTTYPES for location, and AFFECTED_BY for bitvector)\n\r", ch );
}
send_to_char( "Skill being any skill or spell.\n\r", ch );
return;
}
if( get_trust( ch ) > LEVEL_SUB_IMPLEM && !str_cmp( arg1, "save" ) && !str_cmp( argument, "table" ) )
{
if( !str_cmp( arg2, "skill" ) )
{
send_to_char( "Saving skill table...\n\r", ch );
save_skill_table( );
save_classes( );
/*
* save_races();
*/
return;
}
if( !str_cmp( arg2, "herb" ) )
{
send_to_char( "Saving herb table...\n\r", ch );
save_herb_table( );
return;
}
}
if( get_trust( ch ) > LEVEL_SUB_IMPLEM
&& !str_cmp( arg1, "create" )
&& ( !str_cmp( arg2, "skill" ) || !str_cmp( arg2, "herb" ) || !str_cmp( arg2, "ability" ) ) )
{
struct skill_type *skill;
short type = SKILL_UNKNOWN;
if( !str_cmp( arg2, "herb" ) )
{
type = SKILL_HERB;
if( top_herb >= MAX_HERB )
{
ch_printf( ch, "The current top herb is %d, which is the maximum. "
"To add more herbs,\n\rMAX_HERB will have to be "
"raised in mud.h, and the mud recompiled.\n\r", top_herb );
return;
}
}
else if( top_sn >= MAX_SKILL )
{
ch_printf( ch, "The current top sn is %d, which is the maximum. "
"To add more skills,\n\rMAX_SKILL will have to be "
"raised in mud.h, and the mud recompiled.\n\r", top_sn );
return;
}
CREATE( skill, struct skill_type, 1 );
skill->slot = 0;
if( type == SKILL_HERB )
{
int max, x;
herb_table[top_herb++] = skill;
for( max = x = 0; x < top_herb - 1; x++ )
if( herb_table[x] && herb_table[x]->slot > max )
max = herb_table[x]->slot;
skill->slot = max + 1;
}
else
skill_table[top_sn++] = skill;
skill->min_mana = 0;
skill->name = str_dup( argument );
skill->noun_damage = str_dup( "" );
skill->msg_off = str_dup( "" );
skill->spell_fun = spell_smaug;
skill->type = type;
skill->spell_sector = 0;
skill->guild = -1;
if( !str_cmp( arg2, "ability" ) )
skill->type = SKILL_RACIAL;
for( i = 0; i < MAX_PC_CLASS; i++ )
{
skill->skill_level[i] = LEVEL_IMMORTAL;
skill->skill_adept[i] = 95;
}
for( i = 0; i < MAX_PC_RACE; i++ )
{
skill->race_level[i] = LEVEL_IMMORTAL;
skill->race_adept[i] = 95;
}
send_to_char( "Done.\n\r", ch );
return;
}
if( arg1[0] == 'h' )
sn = atoi( arg1 + 1 );
else
sn = atoi( arg1 );
if( get_trust( ch ) > LEVEL_GREATER
&& ( ( arg1[0] == 'h' && is_number( arg1 + 1 ) && ( sn = atoi( arg1 + 1 ) ) >= 0 )
|| ( is_number( arg1 ) && ( sn = atoi( arg1 ) ) >= 0 ) ) )
{
struct skill_type *skill;
if( arg1[0] == 'h' )
{
if( sn >= top_herb )
{
send_to_char( "Herb number out of range.\n\r", ch );
return;
}
skill = herb_table[sn];
}
else
{
if( ( skill = get_skilltype( sn ) ) == NULL )
{
send_to_char( "Skill number out of range.\n\r", ch );
return;
}
sn %= 1000;
}
if( !str_cmp( arg2, "difficulty" ) )
{
skill->difficulty = atoi( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "participants" ) )
{
skill->participants = atoi( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "damtype" ) )
{
int x = get_sdamage( argument );
if( x == -1 )
send_to_char( "Not a spell damage type.\n\r", ch );
else
{
SET_SDAM( skill, x );
send_to_char( "Ok.\n\r", ch );
}
return;
}
if( !str_cmp( arg2, "acttype" ) )
{
int x = get_saction( argument );
if( x == -1 )
send_to_char( "Not a spell action type.\n\r", ch );
else
{
SET_SACT( skill, x );
send_to_char( "Ok.\n\r", ch );
}
return;
}
if( !str_cmp( arg2, "classtype" ) )
{
int x = get_sclass( argument );
if( x == -1 )
send_to_char( "Not a spell class type.\n\r", ch );
else
{
SET_SCLA( skill, x );
send_to_char( "Ok.\n\r", ch );
}
return;
}
if( !str_cmp( arg2, "powertype" ) )
{
int x = get_spower( argument );
if( x == -1 )
send_to_char( "Not a spell power type.\n\r", ch );
else
{
SET_SPOW( skill, x );
send_to_char( "Ok.\n\r", ch );
}
return;
}
if( !str_cmp( arg2, "seffect" ) )
{
int x = get_ssave_effect( argument );
if( x == -1 )
send_to_char( "Not a spell save effect type.\n\r", ch );
else
{
SET_SSAV( skill, x );
send_to_char( "Ok.\n\r", ch );
}
return;
}
if( !str_cmp( arg2, "flag" ) )
{
int x = get_sflag( argument );
if( x == -1 )
send_to_char( "Not a spell flag.\n\r", ch );
else
{
TOGGLE_BIT( skill->flags, 1 << x );
send_to_char( "Ok.\n\r", ch );
}
return;
}
if( !str_cmp( arg2, "saves" ) )
{
int x = get_ssave( argument );
if( x == -1 )
send_to_char( "Not a saving type.\n\r", ch );
else
{
skill->saves = x;
send_to_char( "Ok.\n\r", ch );
}
return;
}
if( !str_cmp( arg2, "code" ) )
{
SPELL_FUN *spellfun;
DO_FUN *dofun;
if( !str_prefix( "do_", argument ) && ( dofun = skill_function( argument ) ) != skill_notfound )
{
skill->skill_fun = dofun;
skill->spell_fun = NULL;
DISPOSE( skill->skill_fun_name );
skill->skill_fun_name = str_dup( argument );
}
else if( ( spellfun = spell_function( argument ) ) != spell_notfound )
{
skill->spell_fun = spellfun;
skill->skill_fun = NULL;
DISPOSE( skill->skill_fun_name );
skill->spell_fun_name = str_dup( argument );
}
else
{
send_to_char( "Not a spell or skill.\n\r", ch );
return;
}
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "target" ) )
{
int x = get_starget( argument );
if( x == -1 )
send_to_char( "Not a valid target type.\n\r", ch );
else
{
skill->target = x;
send_to_char( "Ok.\n\r", ch );
}
return;
}
if( !str_cmp( arg2, "minpos" ) )
{
skill->minimum_position = URANGE( POS_DEAD, atoi( argument ), POS_DRAG );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "minlevel" ) )
{
skill->min_level = URANGE( 1, atoi( argument ), MAX_LEVEL );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "sector" ) )
{
char tmp_arg[MAX_STRING_LENGTH];
while( argument[0] != '\0' )
{
argument = one_argument( argument, tmp_arg );
value = get_secflag( tmp_arg );
if( value < 0 || value > SECT_MAX )
ch_printf( ch, "Unknown flag: %s\n\r", tmp_arg );
else
TOGGLE_BIT( skill->spell_sector, ( 1 << value ) );
}
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "slot" ) )
{
skill->slot = URANGE( 0, atoi( argument ), 30000 );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "mana" ) )
{
skill->min_mana = URANGE( 0, atoi( argument ), 2000 );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "beats" ) )
{
skill->beats = URANGE( 0, atoi( argument ), 120 );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "range" ) )
{
skill->range = URANGE( 0, atoi( argument ), 20 );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "guild" ) )
{
skill->guild = atoi( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "value" ) )
{
skill->value = atoi( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "type" ) )
{
skill->type = get_skill( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "rmaffect" ) )
{
SMAUG_AFF *aff = skill->affects;
SMAUG_AFF *aff_next;
int num = atoi( argument );
int cnt = 1;
if( !aff )
{
send_to_char( "This spell has no special affects to remove.\n\r", ch );
return;
}
if( num == 1 )
{
skill->affects = aff->next;
DISPOSE( aff->duration );
DISPOSE( aff->modifier );
DISPOSE( aff );
send_to_char( "Removed.\n\r", ch );
return;
}
for( ; aff; aff = aff->next )
{
if( ++cnt == num && ( aff_next = aff->next ) != NULL )
{
aff->next = aff_next->next;
DISPOSE( aff_next->duration );
DISPOSE( aff_next->modifier );
DISPOSE( aff_next );
send_to_char( "Removed.\n\r", ch );
return;
}
}
send_to_char( "Not found.\n\r", ch );
return;
}
/*
* affect <location> <modifier> <duration> <bitvector>
*/
if( !str_cmp( arg2, "affect" ) )
{
char location[MAX_INPUT_LENGTH];
char modifier[MAX_INPUT_LENGTH];
char duration[MAX_INPUT_LENGTH];
/*
* char bitvector[MAX_INPUT_LENGTH];
*/
int loc, bit, tmpbit;
SMAUG_AFF *aff;
argument = one_argument( argument, location );
argument = one_argument( argument, modifier );
argument = one_argument( argument, duration );
if( location[0] == '!' )
loc = get_atype( location + 1 ) + REVERSE_APPLY;
else
loc = get_atype( location );
if( ( loc % REVERSE_APPLY ) < 0 || ( loc % REVERSE_APPLY ) >= MAX_APPLY_TYPE )
{
send_to_char( "Unknown affect location. See AFFECTTYPES.\n\r", ch );
return;
}
bit = -1;
if( argument[0] != '\0' )
{
if( ( tmpbit = get_aflag( argument ) ) == -1 )
ch_printf( ch, "Unknown bitvector: %s. See AFFECTED_BY\n\r", argument );
else
bit = tmpbit;
}
CREATE( aff, SMAUG_AFF, 1 );
if( !str_cmp( duration, "0" ) )
duration[0] = '\0';
if( !str_cmp( modifier, "0" ) )
modifier[0] = '\0';
aff->duration = str_dup( duration );
aff->location = loc;
if( loc == APPLY_AFFECT || loc == APPLY_RESISTANT || loc == APPLY_IMMUNE || loc == APPLY_SUSCEPTIBLE )
{
int modval = get_aflag( modifier );
/*
* Sanitize the flag input for the modifier if needed -- Samson
*/
if( modval < 0 )
modval = 0;
snprintf( modifier, MAX_INPUT_LENGTH, "%d", modval );
}
aff->modifier = str_dup( modifier );
aff->bitvector = bit;
aff->next = skill->affects;
skill->affects = aff;
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "level" ) )
{
char arg3[MAX_INPUT_LENGTH];
int class;
argument = one_argument( argument, arg3 );
class = atoi( arg3 );
if( class >= MAX_PC_CLASS || class < 0 )
send_to_char( "Not a valid class.\n\r", ch );
else
skill->skill_level[class] = URANGE( 0, atoi( argument ), MAX_LEVEL );
return;
}
if( !str_cmp( arg2, "racelevel" ) )
{
char arg3[MAX_INPUT_LENGTH];
int race;
argument = one_argument( argument, arg3 );
race = atoi( arg3 );
if( race >= MAX_PC_RACE || race < 0 )
send_to_char( "Not a valid race.\n\r", ch );
else
skill->race_level[race] = URANGE( 0, atoi( argument ), MAX_LEVEL );
return;
}
if( !str_cmp( arg2, "adept" ) )
{
char arg3[MAX_INPUT_LENGTH];
int class;
argument = one_argument( argument, arg3 );
class = atoi( arg3 );
if( class >= MAX_PC_CLASS || class < 0 )
send_to_char( "Not a valid class.\n\r", ch );
else
skill->skill_adept[class] = URANGE( 0, atoi( argument ), 100 );
return;
}
if( !str_cmp( arg2, "raceadept" ) )
{
char arg3[MAX_INPUT_LENGTH];
int race;
argument = one_argument( argument, arg3 );
race = atoi( arg3 );
if( race >= MAX_PC_RACE || race < 0 )
send_to_char( "Not a valid race.\n\r", ch );
else
skill->race_adept[race] = URANGE( 0, atoi( argument ), 100 );
return;
}
if( !str_cmp( arg2, "name" ) )
{
DISPOSE( skill->name );
skill->name = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "dammsg" ) )
{
DISPOSE( skill->noun_damage );
if( !str_cmp( argument, "clear" ) )
skill->noun_damage = str_dup( "" );
else
skill->noun_damage = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "wearoff" ) )
{
DISPOSE( skill->msg_off );
if( str_cmp( argument, "clear" ) )
skill->msg_off = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "hitchar" ) )
{
if( skill->hit_char )
DISPOSE( skill->hit_char );
if( str_cmp( argument, "clear" ) )
skill->hit_char = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "hitvict" ) )
{
if( skill->hit_vict )
DISPOSE( skill->hit_vict );
if( str_cmp( argument, "clear" ) )
skill->hit_vict = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "hitroom" ) )
{
if( skill->hit_room )
DISPOSE( skill->hit_room );
if( str_cmp( argument, "clear" ) )
skill->hit_room = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "hitdest" ) )
{
if( skill->hit_dest )
DISPOSE( skill->hit_dest );
if( str_cmp( argument, "clear" ) )
skill->hit_dest = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "misschar" ) )
{
if( skill->miss_char )
DISPOSE( skill->miss_char );
if( str_cmp( argument, "clear" ) )
skill->miss_char = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "missvict" ) )
{
if( skill->miss_vict )
DISPOSE( skill->miss_vict );
if( str_cmp( argument, "clear" ) )
skill->miss_vict = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "missroom" ) )
{
if( skill->miss_room )
DISPOSE( skill->miss_room );
if( str_cmp( argument, "clear" ) )
skill->miss_room = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "diechar" ) )
{
if( skill->die_char )
DISPOSE( skill->die_char );
if( str_cmp( argument, "clear" ) )
skill->die_char = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "dievict" ) )
{
if( skill->die_vict )
DISPOSE( skill->die_vict );
if( str_cmp( argument, "clear" ) )
skill->die_vict = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "dieroom" ) )
{
if( skill->die_room )
DISPOSE( skill->die_room );
if( str_cmp( argument, "clear" ) )
skill->die_room = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "immchar" ) )
{
if( skill->imm_char )
DISPOSE( skill->imm_char );
if( str_cmp( argument, "clear" ) )
skill->imm_char = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "immvict" ) )
{
if( skill->imm_vict )
DISPOSE( skill->imm_vict );
if( str_cmp( argument, "clear" ) )
skill->imm_vict = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "immroom" ) )
{
if( skill->imm_room )
DISPOSE( skill->imm_room );
if( str_cmp( argument, "clear" ) )
skill->imm_room = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "dice" ) )
{
if( skill->dice )
DISPOSE( skill->dice );
if( str_cmp( argument, "clear" ) )
skill->dice = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "components" ) )
{
if( skill->components )
DISPOSE( skill->components );
if( str_cmp( argument, "clear" ) )
skill->components = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
if( !str_cmp( arg2, "teachers" ) )
{
if( skill->teachers )
DISPOSE( skill->teachers );
if( str_cmp( argument, "clear" ) )
skill->teachers = str_dup( argument );
send_to_char( "Ok.\n\r", ch );
return;
}
do_sset( ch, "" );
return;
}
if( ( victim = get_char_world( ch, arg1 ) ) == NULL )
{
if( ( sn = skill_lookup( arg1 ) ) >= 0 )
{
sprintf( arg1, "%d %s %s", sn, arg2, argument );
do_sset( ch, arg1 );
}
else
send_to_char( "They aren't here.\n\r", ch );
return;
}
if( IS_NPC( victim ) )
{
send_to_char( "Not on NPC's.\n\r", ch );
return;
}
fAll = !str_cmp( arg2, "all" );
sn = 0;
if( !fAll && ( sn = skill_lookup( arg2 ) ) < 0 )
{
send_to_char( "No such skill or spell.\n\r", ch );
return;
}
/*
* Snarf the value.
*/
if( !is_number( argument ) )
{
send_to_char( "Value must be numeric.\n\r", ch );
return;
}
value = atoi( argument );
if( value < 0 || value > 100 )
{
send_to_char( "Value range is 0 to 100.\n\r", ch );
return;
}
if( fAll )
{
for( sn = 0; sn < top_sn; sn++ )
{
/*
* Fix by Narn to prevent ssetting skills the player shouldn't have.
*/
if( skill_table[sn]->name && ( victim->level >= skill_table[sn]->skill_level[victim->class] || value == 0 ) )
{
if( value == 100 && !IS_IMMORTAL( victim ) )
victim->pcdata->learned[sn] = GET_ADEPT( victim, sn );
else
victim->pcdata->learned[sn] = value;
}
}
}
else
victim->pcdata->learned[sn] = value;
return;
}
void learn_from_success( CHAR_DATA * ch, int sn )
{
int adept, gain, sklvl, percent, schance, lchance, learn;
/* the following added by tommi Jan 6006 inspired by Tarl of AFKmud
the point of the following code is to make skills learn at a much
slower rate than normal
*/
if( skill_table[sn]->type == SKILL_WEAPON )
{
lchance = number_range( 1, 10 );
if( lchance != 5 )
{
return;
}
}
if( skill_table[sn]->type == SKILL_SKILL )
{
lchance = number_range( 1, 5 );
if( lchance != 3 )
{
return;
}
}
if( skill_table[sn]->type == SKILL_SPELL )
{
lchance = number_range( 1, 3 );
if( lchance != 2 )
{
return;
}
}
if( IS_NPC( ch ) || ch->pcdata->learned[sn] <= 0 )
return;
adept = GET_ADEPT( ch, sn );
sklvl = skill_table[sn]->skill_level[ch->class];
if( sklvl == 0 )
sklvl = ch->level;
if( ch->pcdata->learned[sn] < adept )
{
schance = ch->pcdata->learned[sn] + ( 5 * skill_table[sn]->difficulty );
percent = number_percent( );
if( percent >= schance )
learn = 2;
else if( schance - percent > 25 )
return;
else
learn = 1;
ch->pcdata->learned[sn] = UMIN( adept, ch->pcdata->learned[sn] + learn );
if( ch->pcdata->learned[sn] == adept ) /* fully learned! */
{
gain = 1500 * sklvl;
set_char_color( AT_WHITE, ch );
ch_printf( ch, "You are now an adept of %s! You gain %d bonus experience!\n\r", skill_table[sn]->name, gain );
}
else
{
gain = 50 * sklvl;
if( !ch->fighting && sn != gsn_hide && sn != gsn_sneak )
{
set_char_color( AT_WHITE, ch );
ch_printf( ch, "You gain %d experience points from your success!\n\r", gain );
}
}
gain_exp( ch, gain );
}
}
void learn_from_failure( CHAR_DATA * ch, int sn )
{
int adept, schance, lchance;
/* the following added by tommi Jan 6006 inspited by Tarl of AFKmud
the point of the following code is to make skills learn at a much
slower rate than normal
*/
if( skill_table[sn]->type == SKILL_WEAPON )
{
lchance = number_range( 1, 10 );
if( lchance != 5 )
{
return;
}
}
if( skill_table[sn]->type == SKILL_SKILL )
{
lchance = number_range( 1, 5 );
if( lchance != 3 )
{
return;
}
}
if( skill_table[sn]->type == SKILL_SPELL )
{
lchance = number_range( 1, 3 );
if( lchance != 2 )
{
return;
}
}
if( IS_NPC( ch ) || ch->pcdata->learned[sn] <= 0 )
return;
schance = ch->pcdata->learned[sn] + ( 5 * skill_table[sn]->difficulty );
if( schance - number_percent( ) > 25 )
return;
adept = GET_ADEPT( ch, sn );
if( ch->pcdata->learned[sn] < ( adept - 1 ) )
{
ch->pcdata->learned[sn] += 1;
send_to_char("You learn from your mistakes\n\r", ch);
}
}
void do_gouge( CHAR_DATA * ch, char *argument )
{
CHAR_DATA *victim;
AFFECT_DATA af;
short dam;
int schance;
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
if( !can_use_skill( ch, 0, gsn_gouge ) )
{
send_to_char( "You do not yet know of this skill.\n\r", ch );
return;
}
if( ch->mount )
{
send_to_char( "You can't get close enough while mounted.\n\r", ch );
return;
}
if( ( victim = who_fighting( ch ) ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
schance = ( ( get_curr_dex( victim ) - get_curr_dex( ch ) ) * 10 ) + 10;
if( !IS_NPC( ch ) && !IS_NPC( victim ) )
schance += sysdata.gouge_plr_vs_plr;
if( victim->fighting && victim->fighting->who != ch )
schance += sysdata.gouge_nontank;
if( can_use_skill( ch, ( number_percent( ) + schance ), gsn_gouge ) )
{
dam = number_range( 5, ch->level );
global_retcode = damage( ch, victim, dam, gsn_gouge );
if( global_retcode == rNONE )
{
if( !IS_AFFECTED( victim, AFF_BLIND ) )
{
af.type = gsn_blindness;
af.location = APPLY_HITROLL;
af.modifier = -6;
if( !IS_NPC( victim ) && !IS_NPC( ch ) )
af.duration = ( ch->level + 10 ) / get_curr_con( victim );
else
af.duration = 3 + ( ch->level / 15 );
af.bitvector = meb( AFF_BLIND );
affect_to_char( victim, &af );
act( AT_SKILL, "You can't see a thing!", victim, NULL, NULL, TO_CHAR );
}
WAIT_STATE( ch, PULSE_VIOLENCE );
if( !IS_NPC( ch ) && !IS_NPC( victim ) )
{
if( number_bits( 1 ) == 0 )
{
ch_printf( ch, "%s looks momentarily dazed.\n\r", victim->name );
send_to_char( "You are momentarily dazed ...\n\r", victim );
WAIT_STATE( victim, PULSE_VIOLENCE );
}
}
else
WAIT_STATE( victim, PULSE_VIOLENCE );
/*
* Taken out by request - put back in by Thoric
* * This is how it was designed. You'd be a tad stunned
* * if someone gouged you in the eye.
* * Mildly modified by Blodkai, Feb 1998 at request of
* * of pkill Conclave (peaceful use remains the same)
*/
}
else if( global_retcode == rVICT_DIED )
{
act( AT_BLOOD, "Your fingers plunge into your victim's brain, causing immediate death!", ch, NULL, NULL, TO_CHAR );
}
if( global_retcode != rCHAR_DIED && global_retcode != rBOTH_DIED )
learn_from_success( ch, gsn_gouge );
}
else
{
WAIT_STATE( ch, skill_table[gsn_gouge]->beats );
global_retcode = damage( ch, victim, 0, gsn_gouge );
learn_from_failure( ch, gsn_gouge );
}
return;
}
void do_detrap( CHAR_DATA * ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
OBJ_DATA *obj;
OBJ_DATA *trap;
int percent;
bool found = FALSE;
switch ( ch->substate )
{
default:
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
argument = one_argument( argument, arg );
if( !can_use_skill( ch, 0, gsn_detrap ) )
{
send_to_char( "You do not yet know of this skill.\n\r", ch );
return;
}
if( arg[0] == '\0' )
{
send_to_char( "Detrap what?\n\r", ch );
return;
}
if( ms_find_obj( ch ) )
return;
found = FALSE;
if( ch->mount )
{
send_to_char( "You can't do that while mounted.\n\r", ch );
return;
}
if( !ch->in_room->first_content )
{
send_to_char( "You can't find that here.\n\r", ch );
return;
}
for( obj = ch->in_room->first_content; obj; obj = obj->next_content )
{
if( can_see_obj( ch, obj ) && nifty_is_name( arg, obj->name ) )
{
found = TRUE;
break;
}
}
if( !found )
{
send_to_char( "You can't find that here.\n\r", ch );
return;
}
act( AT_ACTION, "You carefully begin your attempt to remove a trap from $p...", ch, obj, NULL, TO_CHAR );
act( AT_ACTION, "$n carefully attempts to remove a trap from $p...", ch, obj, NULL, TO_ROOM );
ch->alloc_ptr = str_dup( obj->name );
add_timer( ch, TIMER_DO_FUN, 3, do_detrap, 1 );
/*
* WAIT_STATE( ch, skill_table[gsn_detrap]->beats );
*/
return;
case 1:
if( !ch->alloc_ptr )
{
send_to_char( "Your detrapping was interrupted!\n\r", ch );
bug( "do_detrap: ch->alloc_ptr NULL!", 0 );
return;
}
strcpy( arg, ch->alloc_ptr );
DISPOSE( ch->alloc_ptr );
ch->alloc_ptr = NULL;
ch->substate = SUB_NONE;
break;
case SUB_TIMER_DO_ABORT:
DISPOSE( ch->alloc_ptr );
ch->substate = SUB_NONE;
send_to_char( "You carefully stop what you were doing.\n\r", ch );
return;
}
if( !ch->in_room->first_content )
{
send_to_char( "You can't find that here.\n\r", ch );
return;
}
for( obj = ch->in_room->first_content; obj; obj = obj->next_content )
{
if( can_see_obj( ch, obj ) && nifty_is_name( arg, obj->name ) )
{
found = TRUE;
break;
}
}
if( !found )
{
send_to_char( "You can't find that here.\n\r", ch );
return;
}
if( ( trap = get_trap( obj ) ) == NULL )
{
send_to_char( "You find no trap on that.\n\r", ch );
return;
}
percent = number_percent( ) - ( ch->level / 15 ) - ( get_curr_lck( ch ) - 16 );
separate_obj( obj );
if( !can_use_skill( ch, percent, gsn_detrap ) )
{
send_to_char( "Ooops!\n\r", ch );
spring_trap( ch, trap );
learn_from_failure( ch, gsn_detrap );
return;
}
extract_obj( trap );
send_to_char( "You successfully remove a trap.\n\r", ch );
learn_from_success( ch, gsn_detrap );
return;
}
void do_dig( CHAR_DATA * ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
OBJ_DATA *obj;
OBJ_DATA *startobj;
bool found, shovel;
EXIT_DATA *pexit;
switch ( ch->substate )
{
default:
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
if( ch->mount )
{
send_to_char( "You can't do that while mounted.\n\r", ch );
return;
}
one_argument( argument, arg );
if( arg[0] != '\0' )
{
if( ( pexit = find_door( ch, arg, TRUE ) ) == NULL && get_dir( arg ) == -1 )
{
send_to_char( "What direction is that?\n\r", ch );
return;
}
if( pexit )
{
if( !IS_SET( pexit->exit_info, EX_DIG ) && !IS_SET( pexit->exit_info, EX_CLOSED ) )
{
send_to_char( "There is no need to dig out that exit.\n\r", ch );
return;
}
}
}
else
{
int sector;
if( IS_PLR_FLAG( ch, PLR_ONMAP ) || IS_ACT_FLAG( ch, ACT_ONMAP ) )
sector = map_sector[ch->map][ch->x][ch->y];
else
sector = ch->in_room->sector_type;
switch ( sector )
{
case SECT_CITY:
send_to_char( "The road is too hard to dig through.\n\r", ch );
return;
case SECT_INSIDE:
send_to_char( "The floor is too hard to dig through.\n\r", ch );
return;
case SECT_WATER_SWIM:
case SECT_WATER_NOSWIM:
case SECT_UNDERWATER:
send_to_char( "You cannot dig here.\n\r", ch );
return;
case SECT_AIR:
send_to_char( "What? In the air?!\n\r", ch );
return;
}
}
add_timer( ch, TIMER_DO_FUN, UMIN( skill_table[gsn_dig]->beats / 10, 3 ), do_dig, 1 );
ch->alloc_ptr = str_dup( arg );
send_to_char( "You begin digging...\n\r", ch );
act( AT_PLAIN, "$n begins digging...", ch, NULL, NULL, TO_ROOM );
return;
case 1:
if( !ch->alloc_ptr )
{
send_to_char( "Your digging was interrupted!\n\r", ch );
act( AT_PLAIN, "$n's digging was interrupted!", ch, NULL, NULL, TO_ROOM );
bug( "do_dig: alloc_ptr NULL", 0 );
return;
}
strcpy( arg, ch->alloc_ptr );
DISPOSE( ch->alloc_ptr );
break;
case SUB_TIMER_DO_ABORT:
DISPOSE( ch->alloc_ptr );
ch->substate = SUB_NONE;
send_to_char( "You stop digging...\n\r", ch );
act( AT_PLAIN, "$n stops digging...", ch, NULL, NULL, TO_ROOM );
return;
}
ch->substate = SUB_NONE;
/*
* not having a shovel makes it harder to succeed
*/
shovel = FALSE;
for( obj = ch->first_carrying; obj; obj = obj->next_content )
if( obj->item_type == ITEM_SHOVEL )
{
shovel = TRUE;
break;
}
/*
* dig out an EX_DIG exit...
*/
if( arg[0] != '\0' )
{
if( ( pexit = find_door( ch, arg, TRUE ) ) != NULL
&& IS_SET( pexit->exit_info, EX_DIG ) && IS_SET( pexit->exit_info, EX_CLOSED ) )
{
/*
* 4 times harder to dig open a passage without a shovel
*/
/*
* if ( (number_percent() * (shovel ? 1 : 4)) <
* LEARNED(ch, gsn_dig) )
*/
if( can_use_skill( ch, ( number_percent( ) * ( shovel ? 1 : 4 ) ), gsn_dig ) )
{
REMOVE_BIT( pexit->exit_info, EX_CLOSED );
send_to_char( "You dig open a passageway!\n\r", ch );
act( AT_PLAIN, "$n digs open a passageway!", ch, NULL, NULL, TO_ROOM );
learn_from_success( ch, gsn_dig );
return;
}
}
learn_from_failure( ch, gsn_dig );
send_to_char( "Your dig did not discover any exit...\n\r", ch );
act( AT_PLAIN, "$n's dig did not discover any exit...", ch, NULL, NULL, TO_ROOM );
return;
}
startobj = ch->in_room->first_content;
found = FALSE;
for( obj = startobj; obj; obj = obj->next_content )
{
/*
* twice as hard to find something without a shovel
*/
if( IS_OBJ_STAT( obj, ITEM_BURIED ) && ( can_use_skill( ch, ( number_percent( ) * ( shovel ? 1 : 2 ) ), gsn_dig ) ) )
/*
* && (number_percent() * (shovel ? 1 : 2)) <
* (IS_NPC(ch) ? 80 : ch->pcdata->learned[gsn_dig]) )
*/
{
found = TRUE;
break;
}
}
if( !found )
{
send_to_char( "Your dig uncovered nothing.\n\r", ch );
act( AT_PLAIN, "$n's dig uncovered nothing.", ch, NULL, NULL, TO_ROOM );
learn_from_failure( ch, gsn_dig );
return;
}
separate_obj( obj );
xREMOVE_BIT( obj->extra_flags, ITEM_BURIED );
act( AT_SKILL, "Your dig uncovered $p!", ch, obj, NULL, TO_CHAR );
act( AT_SKILL, "$n's dig uncovered $p!", ch, obj, NULL, TO_ROOM );
learn_from_success( ch, gsn_dig );
if( obj->item_type == ITEM_CORPSE_PC || obj->item_type == ITEM_CORPSE_NPC )
adjust_favor( ch, 14, 1 );
return;
}
void do_search( CHAR_DATA * ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
OBJ_DATA *obj;
OBJ_DATA *container;
OBJ_DATA *startobj;
int percent, door;
door = -1;
switch ( ch->substate )
{
default:
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
if( ch->mount )
{
send_to_char( "You can't do that while mounted.\n\r", ch );
return;
}
argument = one_argument( argument, arg );
if( arg[0] != '\0' && ( door = get_door( arg ) ) == -1 )
{
container = get_obj_here( ch, arg );
if( !container )
{
send_to_char( "You can't find that here.\n\r", ch );
return;
}
if( container->item_type != ITEM_CONTAINER )
{
send_to_char( "You can't search in that!\n\r", ch );
return;
}
if( IS_SET( container->value[1], CONT_CLOSED ) )
{
send_to_char( "It is closed.\n\r", ch );
return;
}
}
add_timer( ch, TIMER_DO_FUN, UMIN( skill_table[gsn_search]->beats / 10, 3 ), do_search, 1 );
send_to_char( "You begin your search...\n\r", ch );
ch->alloc_ptr = str_dup( arg );
return;
case 1:
if( !ch->alloc_ptr )
{
send_to_char( "Your search was interrupted!\n\r", ch );
bug( "do_search: alloc_ptr NULL", 0 );
return;
}
strcpy( arg, ch->alloc_ptr );
DISPOSE( ch->alloc_ptr );
break;
case SUB_TIMER_DO_ABORT:
DISPOSE( ch->alloc_ptr );
ch->substate = SUB_NONE;
send_to_char( "You stop your search...\n\r", ch );
return;
}
ch->substate = SUB_NONE;
if( arg[0] == '\0' )
startobj = ch->in_room->first_content;
else
{
if( ( door = get_door( arg ) ) != -1 )
startobj = NULL;
else
{
container = get_obj_here( ch, arg );
if( !container )
{
send_to_char( "You can't find that here.\n\r", ch );
return;
}
startobj = container->first_content;
}
}
if( ( !startobj && door == -1 ) || IS_NPC( ch ) )
{
send_to_char( "You find nothing.\n\r", ch );
learn_from_failure( ch, gsn_search );
return;
}
percent = number_percent( ) + number_percent( ) - ( ch->level / 10 );
if( door != -1 )
{
EXIT_DATA *pexit;
if( ( pexit = get_exit( ch->in_room, door ) ) != NULL
&& IS_SET( pexit->exit_info, EX_SECRET )
&& IS_SET( pexit->exit_info, EX_xSEARCHABLE ) && can_use_skill( ch, percent, gsn_search ) )
{
act( AT_SKILL, "Your search reveals the $d!", ch, NULL, pexit->keyword, TO_CHAR );
act( AT_SKILL, "$n finds the $d!", ch, NULL, pexit->keyword, TO_ROOM );
REMOVE_BIT( pexit->exit_info, EX_SECRET );
learn_from_success( ch, gsn_search );
return;
}
}
else
for( obj = startobj; obj; obj = obj->next_content )
{
if( IS_OBJ_STAT( obj, ITEM_HIDDEN ) && can_use_skill( ch, percent, gsn_search ) )
{
separate_obj( obj );
xREMOVE_BIT( obj->extra_flags, ITEM_HIDDEN );
act( AT_SKILL, "Your search reveals $p!", ch, obj, NULL, TO_CHAR );
act( AT_SKILL, "$n finds $p!", ch, obj, NULL, TO_ROOM );
learn_from_success( ch, gsn_search );
return;
}
}
send_to_char( "You find nothing.\n\r", ch );
learn_from_failure( ch, gsn_search );
return;
}
void do_steal( CHAR_DATA * ch, char *argument )
{
char buf[MAX_STRING_LENGTH];
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
CHAR_DATA *victim, *mst;
OBJ_DATA *obj;
int percent;
argument = one_argument( argument, arg1 );
argument = one_argument( argument, arg2 );
if( ch->mount )
{
send_to_char( "You can't do that while mounted.\n\r", ch );
return;
}
if( arg1[0] == '\0' || arg2[0] == '\0' )
{
send_to_char( "Steal what from whom?\n\r", ch );
return;
}
if( ms_find_obj( ch ) )
return;
if( ( victim = get_char_room( ch, arg2 ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
if( victim == ch )
{
send_to_char( "That's pointless.\n\r", ch );
return;
}
if( xIS_SET( ch->in_room->room_flags, ROOM_SAFE ) )
{
set_char_color( AT_MAGIC, ch );
send_to_char( "A magical force interrupts you.\n\r", ch );
return;
}
/*
* Disabled stealing among players because of complaints naked avatars were
* running around stealing eq from equipped pkillers. -- Narn
*/
/*
* if ( check_illegal_psteal( ch, victim ) )
* {
* send_to_char( "You can't steal from that player.\n\r", ch );
* return;
* }
*/
if( !IS_NPC( ch ) && !IS_NPC( victim ) )
{
set_char_color( AT_IMMORT, ch );
send_to_char( "The gods forbid theft between players.\n\r", ch );
return;
}
if( xIS_SET( victim->act, ACT_PACIFIST ) ) /* Gorog */
{
send_to_char( "They are a pacifist - Shame on you!\n\r", ch );
return;
}
WAIT_STATE( ch, skill_table[gsn_steal]->beats );
percent = number_percent( ) + ( IS_AWAKE( victim ) ? 10 : -50 )
- ( get_curr_lck( ch ) - 15 ) + ( get_curr_lck( victim ) - 13 );
/*
* Changed the level check, made it 10 levels instead of five and made the
* victim not attack in the case of a too high level difference. This is
* to allow mobprogs where the mob steals eq without having to put level
* checks into the progs. Also gave the mobs a 10% chance of failure.
*/
if( ch->level + 10 < victim->level )
{
send_to_char( "You really don't want to try that!\n\r", ch );
return;
}
if( victim->position == POS_FIGHTING || !can_use_skill( ch, percent, gsn_steal ) )
{
/*
* Failure.
*/
send_to_char( "Oops...\n\r", ch );
act( AT_ACTION, "$n tried to steal from you!\n\r", ch, NULL, victim, TO_VICT );
act( AT_ACTION, "$n tried to steal from $N.\n\r", ch, NULL, victim, TO_NOTVICT );
sprintf( buf, "%s is a bloody thief!", ch->name );
do_yell( victim, buf );
learn_from_failure( ch, gsn_steal );
if( !IS_NPC( ch ) )
{
if( legal_loot( ch, victim ) )
{
global_retcode = multi_hit( victim, ch, TYPE_UNDEFINED );
}
else
{
/*
* log_string( buf );
*/
if( IS_NPC( ch ) )
{
if( ( mst = ch->master ) == NULL )
return;
}
else
mst = ch;
if( IS_NPC( mst ) )
return;
if( !xIS_SET( mst->act, PLR_THIEF ) )
{
xSET_BIT( mst->act, PLR_THIEF );
set_char_color( AT_WHITE, ch );
send_to_char( "A strange feeling grows deep inside you, and a tingle goes up your spine...\n\r", ch );
set_char_color( AT_IMMORT, ch );
send_to_char( "A deep voice booms inside your head, 'Thou shall now be known as a lowly thief!'\n\r", ch );
set_char_color( AT_WHITE, ch );
send_to_char( "You feel as if your soul has been revealed for all to see.\n\r", ch );
save_char_obj( mst );
}
}
}
return;
}
if( !str_cmp( arg1, "coin" ) || !str_cmp( arg1, "coins" ) || !str_cmp( arg1, "gold" ) )
{
int amount;
amount = ( int )( victim->gold * number_range( 1, 10 ) / 100 );
if( amount <= 0 )
{
send_to_char( "You couldn't get any gold.\n\r", ch );
learn_from_failure( ch, gsn_steal );
return;
}
ch->gold += amount;
victim->gold -= amount;
ch_printf( ch, "Aha! You got %d gold coins.\n\r", amount );
learn_from_success( ch, gsn_steal );
return;
}
if( ( obj = get_obj_carry( victim, arg1 ) ) == NULL )
{
send_to_char( "You can't seem to find it.\n\r", ch );
learn_from_failure( ch, gsn_steal );
return;
}
if( !can_drop_obj( ch, obj )
|| IS_OBJ_STAT( obj, ITEM_INVENTORY ) || IS_OBJ_STAT( obj, ITEM_PROTOTYPE ) || obj->level > ch->level )
{
send_to_char( "You can't manage to pry it away.\n\r", ch );
learn_from_failure( ch, gsn_steal );
return;
}
if( ch->carry_number + ( get_obj_number( obj ) / obj->count ) > can_carry_n( ch ) )
{
send_to_char( "You have your hands full.\n\r", ch );
learn_from_failure( ch, gsn_steal );
return;
}
if( ch->carry_weight + ( get_obj_weight( obj ) / obj->count ) > can_carry_w( ch ) )
{
send_to_char( "You can't carry that much weight.\n\r", ch );
learn_from_failure( ch, gsn_steal );
return;
}
separate_obj( obj );
obj_from_char( obj );
obj_to_char( obj, ch );
send_to_char( "Ok.\n\r", ch );
learn_from_success( ch, gsn_steal );
adjust_favor( ch, 9, 1 );
return;
}
void do_backstab( CHAR_DATA * ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
OBJ_DATA *obj;
int percent;
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't do that right now.\n\r", ch );
return;
}
one_argument( argument, arg );
if( ch->mount )
{
send_to_char( "You can't get close enough while mounted.\n\r", ch );
return;
}
if( arg[0] == '\0' )
{
send_to_char( "Backstab whom?\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( "How can you sneak up on yourself?\n\r", ch );
return;
}
if( is_safe( ch, victim, TRUE ) )
return;
if( !IS_NPC( ch ) && !IS_NPC( victim ) && xIS_SET( ch->act, PLR_NICE ) )
{
send_to_char( "You are too nice to do that.\n\r", ch );
return;
}
/*
* Added stabbing weapon. -Narn
*/
if( !( obj = get_eq_char( ch, WEAR_WIELD ) ) )
{
send_to_char( "You need to wield a piercing weapon.\n\r", ch );
return;
}
if( obj->value[3] != DAM_PIERCE )
{
send_to_char( "You need to wield a piercing weapon to backstab.\n\r", ch );
return;
}
if( victim->fighting )
{
send_to_char( "You can't backstab someone who is in combat.\n\r", ch );
return;
}
if( IS_AFFECTED( victim, AFF_SNEAK ) )
{
act( AT_RED, "$N see's you comming and spins around deflecting your backstab.", ch, NULL, victim, TO_CHAR );
act( AT_RED, "You see $n attempt to backstab you, but deftly move out of the way to counter attack.", ch, NULL, victim,
TO_VICT );
global_retcode = damage( victim, ch, 100, gsn_backstab );
check_illegal_pk( ch, victim );
return;
}
/*
* Can backstab a char even if it's hurt as long as it's sleeping. -Narn
*/
if( victim->hit < victim->max_hit && IS_AWAKE( victim ) )
{
act( AT_PLAIN, "$N is hurt and suspicious ... you can't sneak up.", ch, NULL, victim, TO_CHAR );
return;
}
percent = number_percent( ) - ( get_curr_lck( ch ) - 14 ) + ( get_curr_lck( victim ) - 13 );
check_attacker( ch, victim );
WAIT_STATE( ch, skill_table[gsn_backstab]->beats );
if( !IS_AWAKE( victim ) || can_use_skill( ch, percent, gsn_backstab ) )
{
learn_from_success( ch, gsn_backstab );
act( AT_RED, "You move swiftly behind $N and stab deeply into their back.", ch, NULL, victim, TO_CHAR );
act( AT_RED, "$N crys out in pain from $n's backstab.", ch, NULL, victim, TO_ROOM );
global_retcode = multi_hit( ch, victim, gsn_backstab );
adjust_favor( ch, 10, 1 );
check_illegal_pk( ch, victim );
}
else
{
learn_from_failure( ch, gsn_backstab );
act( AT_RED, "You fail to backstab $N.", ch, NULL, victim, TO_CHAR );
global_retcode = damage( ch, victim, 0, gsn_backstab );
check_illegal_pk( ch, victim );
}
return;
}
void do_rescue( CHAR_DATA * ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
CHAR_DATA *fch;
int percent;
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
if( IS_AFFECTED( ch, AFF_BERSERK ) )
{
send_to_char( "You aren't thinking clearly...\n\r", ch );
return;
}
one_argument( argument, arg );
if( arg[0] == '\0' )
{
send_to_char( "Rescue whom?\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( "How about fleeing instead?\n\r", ch );
return;
}
if( ch->mount )
{
send_to_char( "You can't do that while mounted.\n\r", ch );
return;
}
if( !IS_NPC( ch ) && IS_NPC( victim ) )
{
send_to_char( "They don't need your help!\n\r", ch );
return;
}
if( !ch->fighting )
{
send_to_char( "Too late...\n\r", ch );
return;
}
if( ( fch = who_fighting( victim ) ) == NULL )
{
send_to_char( "They are not fighting right now.\n\r", ch );
return;
}
if( who_fighting( victim ) == ch )
{
send_to_char( "Just running away would be better...\n\r", ch );
return;
}
if( IS_AFFECTED( victim, AFF_BERSERK ) )
{
send_to_char( "Stepping in front of a berserker would not be an intelligent decision.\n\r", ch );
return;
}
percent = number_percent( ) - ( get_curr_lck( ch ) - 14 ) - ( get_curr_lck( victim ) - 16 );
WAIT_STATE( ch, skill_table[gsn_rescue]->beats );
if( !can_use_skill( ch, percent, gsn_rescue ) )
{
send_to_char( "You fail the rescue.\n\r", ch );
act( AT_SKILL, "$n tries to rescue you!", ch, NULL, victim, TO_VICT );
act( AT_SKILL, "$n tries to rescue $N!", ch, NULL, victim, TO_NOTVICT );
learn_from_failure( ch, gsn_rescue );
return;
}
act( AT_SKILL, "You rescue $N!", ch, NULL, victim, TO_CHAR );
act( AT_SKILL, "$n rescues you!", ch, NULL, victim, TO_VICT );
act( AT_SKILL, "$n moves in front of $N!", ch, NULL, victim, TO_NOTVICT );
learn_from_success( ch, gsn_rescue );
adjust_favor( ch, 8, 1 );
stop_fighting( fch, FALSE );
stop_fighting( victim, FALSE );
if( ch->fighting )
stop_fighting( ch, FALSE );
set_fighting( ch, fch );
set_fighting( fch, ch );
return;
}
void do_kick( CHAR_DATA * ch, char *argument )
{
CHAR_DATA *victim;
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
if( !IS_NPC( ch ) && ch->level < skill_table[gsn_kick]->skill_level[ch->class] )
{
send_to_char( "You better leave the martial arts to fighters.\n\r", ch );
return;
}
if( argument[0] == '\0' )
{
if( ( victim = who_fighting( ch ) ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
}
else if( argument[0] != '\0' )
{
if( ( victim = get_char_room( ch, argument ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
}
WAIT_STATE( ch, skill_table[gsn_kick]->beats );
if( can_use_skill( ch, number_percent( ), gsn_kick ) )
{
learn_from_success( ch, gsn_kick );
act( AT_RED, "You kick $N.", ch, NULL, victim, TO_CHAR );
act( AT_RED, "$N gets kicked by $n", ch, NULL, victim, TO_ROOM );
global_retcode = damage( ch, victim, number_range( 15, ch->level * 2 ), gsn_kick );
}
else
{
learn_from_failure( ch, gsn_kick );
act( AT_RED, "Your kick misses $N.", ch, NULL, victim, TO_CHAR );
global_retcode = damage( ch, victim, 0, gsn_kick );
}
return;
}
void do_headbutt( CHAR_DATA * ch, char *argument )
{
CHAR_DATA *victim;
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
if( !IS_NPC( ch ) && ch->level < skill_table[gsn_headbutt]->skill_level[ch->class] )
{
send_to_char( "You better leave the martial arts to fighters.\n\r", ch );
return;
}
if( argument[0] == '\0' )
{
if( ( victim = who_fighting( ch ) ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
}
else if( argument[0] != '\0' )
{
if( ( victim = get_char_room( ch, argument ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
}
WAIT_STATE( ch, skill_table[gsn_headbutt]->beats );
if( can_use_skill( ch, number_percent( ), gsn_headbutt ) )
{
learn_from_success( ch, gsn_headbutt );
act( AT_RED, "You headbutt $N.", ch, NULL, victim, TO_CHAR );
act( AT_RED, "$N gets headbutted by $n", ch, NULL, victim, TO_ROOM );
global_retcode = damage( ch, victim, number_range( 15, ch->level * 2 ), gsn_headbutt );
}
else
{
learn_from_failure( ch, gsn_headbutt );
act( AT_RED, "Your headbutt misses $N.", ch, NULL, victim, TO_CHAR );
global_retcode = damage( ch, victim, 0, gsn_headbutt );
}
return;
}
void do_jab( CHAR_DATA * ch, char *argument )
{
CHAR_DATA *victim;
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
if( !IS_NPC( ch ) && ch->level < skill_table[gsn_jab]->skill_level[ch->class] )
{
send_to_char( "You better leave the martial arts to fighters.\n\r", ch );
return;
}
if( argument[0] == '\0' )
{
if( ( victim = who_fighting( ch ) ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
}
else if( argument[0] != '\0' )
{
if( ( victim = get_char_room( ch, argument ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
}
WAIT_STATE( ch, skill_table[gsn_jab]->beats );
if( can_use_skill( ch, number_percent( ), gsn_jab ) )
{
learn_from_success( ch, gsn_jab );
act( AT_RED, "You jab $N.", ch, NULL, victim, TO_CHAR );
act( AT_RED, "$N gets jabed by $n", ch, NULL, victim, TO_ROOM );
global_retcode = damage( ch, victim, number_range( 15, ch->level * 2 ), gsn_jab );
}
else
{
learn_from_failure( ch, gsn_jab );
act( AT_RED, "Your jab misses $N.", ch, NULL, victim, TO_CHAR );
global_retcode = damage( ch, victim, 0, gsn_jab );
}
return;
}
void do_knee( CHAR_DATA * ch, char *argument )
{
CHAR_DATA *victim;
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
if( !IS_NPC( ch ) && ch->level < skill_table[gsn_knee]->skill_level[ch->class] )
{
send_to_char( "You better leave the martial arts to fighters.\n\r", ch );
return;
}
if( argument[0] == '\0' )
{
if( ( victim = who_fighting( ch ) ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
}
else if( argument[0] != '\0' )
{
if( ( victim = get_char_room( ch, argument ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
}
WAIT_STATE( ch, skill_table[gsn_knee]->beats );
if( can_use_skill( ch, number_percent( ), gsn_knee ) )
{
learn_from_success( ch, gsn_knee );
act( AT_RED, "You knee $N.", ch, NULL, victim, TO_CHAR );
act( AT_RED, "$N gets kneeed by $n", ch, NULL, victim, TO_ROOM );
global_retcode = damage( ch, victim, number_range( 15, ch->level * 2 ), gsn_knee );
}
else
{
learn_from_failure( ch, gsn_knee );
act( AT_RED, "Your knee misses $N.", ch, NULL, victim, TO_CHAR );
global_retcode = damage( ch, victim, 0, gsn_knee );
}
return;
}
void do_roundhouse( CHAR_DATA * ch, char *argument )
{
CHAR_DATA *victim;
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
if( !IS_NPC( ch ) && ch->level < skill_table[gsn_roundhouse]->skill_level[ch->class] )
{
send_to_char( "You better leave the martial arts to fighters.\n\r", ch );
return;
}
if( argument[0] == '\0' )
{
if( ( victim = who_fighting( ch ) ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
}
else if( argument[0] != '\0' )
{
if( ( victim = get_char_room( ch, argument ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
}
WAIT_STATE( ch, skill_table[gsn_roundhouse]->beats );
if( can_use_skill( ch, number_percent( ), gsn_roundhouse ) )
{
learn_from_success( ch, gsn_roundhouse );
act( AT_RED, "You roundhouse $N.", ch, NULL, victim, TO_CHAR );
act( AT_RED, "$N gets roundhouseed by $n", ch, NULL, victim, TO_ROOM );
global_retcode = damage( ch, victim, number_range( 15, ch->level * 2 ), gsn_roundhouse );
}
else
{
learn_from_failure( ch, gsn_roundhouse );
act( AT_RED, "Your roundhouse misses $N.", ch, NULL, victim, TO_CHAR );
global_retcode = damage( ch, victim, 0, gsn_roundhouse );
}
return;
}
void do_spinkick( CHAR_DATA * ch, char *argument )
{
CHAR_DATA *victim;
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
if( !IS_NPC( ch ) && ch->level < skill_table[gsn_spinkick]->skill_level[ch->class] )
{
send_to_char( "You better leave the martial arts to fighters.\n\r", ch );
return;
}
if( argument[0] == '\0' )
{
if( ( victim = who_fighting( ch ) ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
}
else if( argument[0] != '\0' )
{
if( ( victim = get_char_room( ch, argument ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
}
WAIT_STATE( ch, skill_table[gsn_spinkick]->beats );
if( can_use_skill( ch, number_percent( ), gsn_spinkick ) )
{
learn_from_success( ch, gsn_spinkick );
act( AT_RED, "You spinkick $N.", ch, NULL, victim, TO_CHAR );
act( AT_RED, "$N gets spinkicked by $n", ch, NULL, victim, TO_ROOM );
global_retcode = damage( ch, victim, number_range( 15, ch->level * 2 ), gsn_spinkick );
}
else
{
learn_from_failure( ch, gsn_spinkick );
act( AT_RED, "Your spinkick misses $N.", ch, NULL, victim, TO_CHAR );
global_retcode = damage( ch, victim, 0, gsn_spinkick );
}
return;
}
void do_uppercut( CHAR_DATA * ch, char *argument )
{
CHAR_DATA *victim;
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
if( !IS_NPC( ch ) && ch->level < skill_table[gsn_uppercut]->skill_level[ch->class] )
{
send_to_char( "You better leave the martial arts to fighters.\n\r", ch );
return;
}
if( argument[0] == '\0' )
{
if( ( victim = who_fighting( ch ) ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
}
else if( argument[0] != '\0' )
{
if( ( victim = get_char_room( ch, argument ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
}
WAIT_STATE( ch, skill_table[gsn_uppercut]->beats );
if( can_use_skill( ch, number_percent( ), gsn_uppercut ) )
{
learn_from_success( ch, gsn_uppercut );
act( AT_RED, "You uppercut $N.", ch, NULL, victim, TO_CHAR );
act( AT_RED, "$N gets uppercuted by $n", ch, NULL, victim, TO_ROOM );
global_retcode = damage( ch, victim, number_range( 15, ch->level * 2 ), gsn_uppercut );
}
else
{
learn_from_failure( ch, gsn_uppercut );
act( AT_RED, "Your uppercut misses $N.", ch, NULL, victim, TO_CHAR );
global_retcode = damage( ch, victim, 0, gsn_uppercut );
}
return;
}
void do_punch( CHAR_DATA * ch, char *argument )
{
CHAR_DATA *victim;
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
if( !IS_NPC( ch ) && ch->level < skill_table[gsn_punch]->skill_level[ch->class] )
{
send_to_char( "You better leave the martial arts to fighters.\n\r", ch );
return;
}
if( argument[0] == '\0' )
{
if( ( victim = who_fighting( ch ) ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
}
else if( argument[0] != '\0' )
{
if( ( victim = get_char_room( ch, argument ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
}
WAIT_STATE( ch, skill_table[gsn_punch]->beats );
if( can_use_skill( ch, number_percent( ), gsn_punch ) )
{
learn_from_success( ch, gsn_punch );
act( AT_RED, "You punch $N in the face.", ch, NULL, victim, TO_CHAR );
act( AT_RED, "$N gets a well timed punch in the face from $n.", ch, NULL, victim, TO_ROOM );
global_retcode = damage( ch, victim, number_range( 15, ch->level * 2 ), gsn_punch );
}
else
{
learn_from_failure( ch, gsn_punch );
act( AT_RED, "Your punch flys wildly through the air missing $N.", ch, NULL, victim, TO_CHAR );
global_retcode = damage( ch, victim, 0, gsn_punch );
}
return;
}
void do_bash( CHAR_DATA * ch, char *argument )
{
CHAR_DATA *victim;
int schance;
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
if( !IS_NPC( ch ) && ch->level < skill_table[gsn_bash]->skill_level[ch->class] )
{
send_to_char( "You better leave the martial arts to fighters.\n\r", ch );
return;
}
if( ( victim = who_fighting( ch ) ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
schance = ( ( ( get_curr_dex( victim ) + get_curr_str( victim ) )
- ( get_curr_dex( ch ) + get_curr_str( ch ) ) ) * 10 ) + 10;
if( !IS_NPC( ch ) && !IS_NPC( victim ) )
schance += sysdata.bash_plr_vs_plr;
if( victim->fighting && victim->fighting->who != ch )
schance += sysdata.bash_nontank;
WAIT_STATE( ch, skill_table[gsn_bash]->beats );
if( can_use_skill( ch, ( number_percent( ) + schance ), gsn_bash ) )
{
learn_from_success( ch, gsn_bash );
/*
* do not change anything here! -Thoric
*/
WAIT_STATE( victim, 2 * PULSE_VIOLENCE );
victim->position = POS_SITTING;
act( AT_RED, "You run head first at $N.", ch, NULL, victim, TO_CHAR );
act( AT_RED, "$N gets slammed by a well timed bash from $n.", ch, NULL, victim, TO_ROOM );
global_retcode = damage( ch, victim, number_range( 15, ch->level ) * 2, gsn_bash );
}
else
{
learn_from_failure( ch, gsn_bash );
act( AT_RED, "You fall flat on your face.", ch, NULL, victim, TO_CHAR );
act( AT_RED, "$n trips and falls flat on his face.", ch, NULL, victim, TO_ROOM );
global_retcode = damage( ch, victim, 0, gsn_bash );
}
return;
}
void do_stun( CHAR_DATA * ch, char *argument )
{
CHAR_DATA *victim;
AFFECT_DATA af;
int schance;
bool fail;
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
if( !IS_NPC( ch ) && ch->level < skill_table[gsn_stun]->skill_level[ch->class] )
{
send_to_char( "You better leave the martial arts to fighters.\n\r", ch );
return;
}
if( ( victim = who_fighting( ch ) ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
if( !IS_NPC( ch ) && ch->move < ch->max_move / 10 )
{
set_char_color( AT_SKILL, ch );
send_to_char( "You are far too tired to do that.\n\r", ch );
return; /* missing return fixed March 11/96 */
}
WAIT_STATE( ch, skill_table[gsn_stun]->beats );
fail = FALSE;
schance = ris_save( victim, ch->level, RIS_PARALYSIS );
if( schance == 1000 )
fail = TRUE;
else
fail = saves_para_petri( schance, victim );
schance = ( ( ( get_curr_dex( victim ) + get_curr_str( victim ) )
- ( get_curr_dex( ch ) + get_curr_str( ch ) ) ) * 10 ) + 10;
/*
* harder for player to stun another player
*/
if( !IS_NPC( ch ) && !IS_NPC( victim ) )
schance += sysdata.stun_plr_vs_plr;
else
schance += sysdata.stun_regular;
if( !fail && can_use_skill( ch, ( number_percent( ) + schance ), gsn_stun ) )
{
learn_from_success( ch, gsn_stun );
/*
* DO *NOT* CHANGE! -Thoric
*/
if( !IS_NPC( ch ) )
ch->move -= ch->max_move / 10;
WAIT_STATE( ch, 2 * PULSE_VIOLENCE );
WAIT_STATE( victim, PULSE_VIOLENCE );
act( AT_SKILL, "$N smashes into you, leaving you stunned!", victim, NULL, ch, TO_CHAR );
act( AT_SKILL, "You smash into $N, leaving $M stunned!", ch, NULL, victim, TO_CHAR );
act( AT_SKILL, "$n smashes into $N, leaving $M stunned!", ch, NULL, victim, TO_NOTVICT );
if( !IS_AFFECTED( victim, AFF_PARALYSIS ) )
{
af.type = gsn_stun;
af.location = APPLY_AC;
af.modifier = 20;
af.duration = 3;
af.bitvector = meb( AFF_PARALYSIS );
affect_to_char( victim, &af );
update_pos( victim );
}
}
else
{
WAIT_STATE( ch, 2 * PULSE_VIOLENCE );
if( !IS_NPC( ch ) )
ch->move -= ch->max_move / 15;
learn_from_failure( ch, gsn_stun );
act( AT_SKILL, "$n charges at you screaming, but you dodge out of the way.", ch, NULL, victim, TO_VICT );
act( AT_SKILL, "You try to stun $N, but $E dodges out of the way.", ch, NULL, victim, TO_CHAR );
act( AT_SKILL, "$n charges screaming at $N, but keeps going right on past.", ch, NULL, victim, TO_NOTVICT );
}
return;
}
/*
* Disarm a creature.
* Caller must check for successful attack.
* Check for loyalty flag (weapon disarms to inventory) for pkillers -Blodkai
*/
void disarm( CHAR_DATA * ch, CHAR_DATA * victim )
{
OBJ_DATA *obj, *tmpobj;
if( ( obj = get_eq_char( victim, WEAR_WIELD ) ) == NULL )
return;
if( ( tmpobj = get_eq_char( victim, WEAR_DUAL_WIELD ) ) != NULL && number_bits( 1 ) == 0 )
obj = tmpobj;
if( get_eq_char( ch, WEAR_WIELD ) == NULL && number_bits( 1 ) == 0 )
{
learn_from_failure( ch, gsn_disarm );
return;
}
if( IS_NPC( ch ) && !can_see_obj( ch, obj ) && number_bits( 1 ) == 0 )
{
learn_from_failure( ch, gsn_disarm );
return;
}
if( check_grip( ch, victim ) )
{
learn_from_failure( ch, gsn_disarm );
return;
}
act( AT_RED, "$n DISARMS you, sending your weapon flying accross the room!", ch, NULL, victim, TO_VICT );
act( AT_SKILL, "You disarm $N sending their weapon flying accross the room", ch, NULL, victim, TO_CHAR );
act( AT_SKILL, "$n disarms $N!", ch, NULL, victim, TO_NOTVICT );
learn_from_success( ch, gsn_disarm );
if( obj == get_eq_char( victim, WEAR_WIELD ) && ( tmpobj = get_eq_char( victim, WEAR_DUAL_WIELD ) ) != NULL )
tmpobj->wear_loc = WEAR_WIELD;
obj_from_char( obj );
obj_to_char( obj, victim );
return;
}
void do_disarm( CHAR_DATA * ch, char *argument )
{
CHAR_DATA *victim;
OBJ_DATA *obj;
int percent;
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
if( !IS_NPC( ch ) && ch->level < skill_table[gsn_disarm]->skill_level[ch->class] )
{
send_to_char( "You don't know how to disarm opponents.\n\r", ch );
return;
}
if( get_eq_char( ch, WEAR_WIELD ) == NULL )
{
send_to_char( "You must wield a weapon to disarm.\n\r", ch );
return;
}
if( ( victim = who_fighting( ch ) ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
if( ( obj = get_eq_char( victim, WEAR_WIELD ) ) == NULL )
{
send_to_char( "Your opponent is not wielding a weapon.\n\r", ch );
return;
}
WAIT_STATE( ch, skill_table[gsn_disarm]->beats );
percent = number_percent( ) + victim->level - ch->level - ( get_curr_lck( ch ) - 15 ) + ( get_curr_lck( victim ) - 15 );
if( !can_see_obj( ch, obj ) )
percent += 10;
if( can_use_skill( ch, ( percent * 3 / 2 ), gsn_disarm ) )
disarm( ch, victim );
else
{
send_to_char( "You failed.\n\r", ch );
learn_from_failure( ch, gsn_disarm );
}
return;
}
/*
* Trip a creature.
* Caller must check for successful attack.
*/
void trip( CHAR_DATA * ch, CHAR_DATA * victim )
{
if( IS_AFFECTED( victim, AFF_FLYING ) || IS_AFFECTED( victim, AFF_FLOATING ) )
return;
if( victim->mount )
{
if( IS_AFFECTED( victim->mount, AFF_FLYING ) || IS_AFFECTED( victim->mount, AFF_FLOATING ) )
return;
act( AT_SKILL, "$n trips your mount and you fall off!", ch, NULL, victim, TO_VICT );
act( AT_SKILL, "You trip $N's mount and $N falls off!", ch, NULL, victim, TO_CHAR );
act( AT_SKILL, "$n trips $N's mount and $N falls off!", ch, NULL, victim, TO_NOTVICT );
xREMOVE_BIT( victim->mount->act, ACT_MOUNTED );
victim->mount = NULL;
WAIT_STATE( ch, 2 * PULSE_VIOLENCE );
WAIT_STATE( victim, 2 * PULSE_VIOLENCE );
victim->position = POS_RESTING;
return;
}
if( victim->wait == 0 )
{
act( AT_SKILL, "$n trips you and you go down!", ch, NULL, victim, TO_VICT );
act( AT_SKILL, "You trip $N and $N goes down!", ch, NULL, victim, TO_CHAR );
act( AT_SKILL, "$n trips $N and $N goes down!", ch, NULL, victim, TO_NOTVICT );
WAIT_STATE( ch, 2 * PULSE_VIOLENCE );
WAIT_STATE( victim, 2 * PULSE_VIOLENCE );
victim->position = POS_RESTING;
}
return;
}
void do_pick( CHAR_DATA * ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *gch;
OBJ_DATA *obj;
EXIT_DATA *pexit;
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
one_argument( argument, arg );
if( arg[0] == '\0' )
{
send_to_char( "Pick what?\n\r", ch );
return;
}
if( ms_find_obj( ch ) )
return;
if( ch->mount )
{
send_to_char( "You can't do that while mounted.\n\r", ch );
return;
}
WAIT_STATE( ch, skill_table[gsn_pick_lock]->beats );
/*
* look for guards
*/
for( gch = ch->in_room->first_person; gch; gch = gch->next_in_room )
{
if( IS_NPC( gch ) && IS_AWAKE( gch ) && ch->level + 5 < gch->level )
{
act( AT_PLAIN, "$N is standing too close to the lock.", ch, NULL, gch, TO_CHAR );
return;
}
}
if( !can_use_skill( ch, number_percent( ), gsn_pick_lock ) )
{
send_to_char( "You failed.\n\r", ch );
learn_from_failure( ch, gsn_pick_lock );
/*
* for ( gch = ch->in_room->first_person; gch; gch = gch->next_in_room )
* {
* if ( IS_NPC(gch) && IS_AWAKE(gch) && xIS_SET(gch->act, ACT_GUARDIAN ) )
* multi_hit( gch, ch, TYPE_UNDEFINED );
* }
*/
return;
}
if( ( pexit = find_door( ch, arg, TRUE ) ) != NULL )
{
/*
* 'pick door'
*/
/*
* ROOM_INDEX_DATA *to_room;
*//*
* Unused
*/
EXIT_DATA *pexit_rev;
if( !IS_SET( pexit->exit_info, EX_CLOSED ) )
{
send_to_char( "It's not closed.\n\r", ch );
return;
}
if( pexit->key < 0 )
{
send_to_char( "It can't be picked.\n\r", ch );
return;
}
if( !IS_SET( pexit->exit_info, EX_LOCKED ) )
{
send_to_char( "It's already unlocked.\n\r", ch );
return;
}
if( IS_SET( pexit->exit_info, EX_PICKPROOF ) )
{
send_to_char( "You failed.\n\r", ch );
learn_from_failure( ch, gsn_pick_lock );
check_room_for_traps( ch, TRAP_PICK | trap_door[pexit->vdir] );
return;
}
REMOVE_BIT( pexit->exit_info, EX_LOCKED );
send_to_char( "*Click*\n\r", ch );
act( AT_ACTION, "$n picks the $d.", ch, NULL, pexit->keyword, TO_ROOM );
learn_from_success( ch, gsn_pick_lock );
adjust_favor( ch, 9, 1 );
/*
* pick the other side
*/
if( ( pexit_rev = pexit->rexit ) != NULL && pexit_rev->to_room == ch->in_room )
{
REMOVE_BIT( pexit_rev->exit_info, EX_LOCKED );
}
check_room_for_traps( ch, TRAP_PICK | trap_door[pexit->vdir] );
return;
}
if( ( obj = get_obj_here( ch, arg ) ) != NULL )
{
/*
* 'pick object'
*/
if( obj->item_type != ITEM_CONTAINER )
{
send_to_char( "That's not a container.\n\r", ch );
return;
}
if( !IS_SET( obj->value[1], CONT_CLOSED ) )
{
send_to_char( "It's not closed.\n\r", ch );
return;
}
if( obj->value[2] < 0 )
{
send_to_char( "It can't be unlocked.\n\r", ch );
return;
}
if( !IS_SET( obj->value[1], CONT_LOCKED ) )
{
send_to_char( "It's already unlocked.\n\r", ch );
return;
}
if( IS_SET( obj->value[1], CONT_PICKPROOF ) )
{
send_to_char( "You failed.\n\r", ch );
learn_from_failure( ch, gsn_pick_lock );
check_for_trap( ch, obj, TRAP_PICK );
return;
}
separate_obj( obj );
REMOVE_BIT( obj->value[1], CONT_LOCKED );
send_to_char( "*Click*\n\r", ch );
act( AT_ACTION, "$n picks $p.", ch, obj, NULL, TO_ROOM );
learn_from_success( ch, gsn_pick_lock );
adjust_favor( ch, 9, 1 );
check_for_trap( ch, obj, TRAP_PICK );
return;
}
ch_printf( ch, "You see no %s here.\n\r", arg );
return;
}
void do_sneak( CHAR_DATA * ch, char *argument )
{
AFFECT_DATA af;
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
if( ch->mount )
{
send_to_char( "You can't do that while mounted.\n\r", ch );
return;
}
send_to_char( "You attempt to move silently.\n\r", ch );
affect_strip( ch, gsn_sneak );
if( can_use_skill( ch, number_percent( ), gsn_sneak ) )
{
af.type = gsn_sneak;
af.duration = ch->level * DUR_CONV;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = meb( AFF_SNEAK );
affect_to_char( ch, &af );
learn_from_success( ch, gsn_sneak );
}
else
learn_from_failure( ch, gsn_sneak );
return;
}
void do_hide( CHAR_DATA * ch, char *argument )
{
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
if( ch->mount )
{
send_to_char( "You can't do that while mounted.\n\r", ch );
return;
}
send_to_char( "You attempt to hide.\n\r", ch );
if( IS_AFFECTED( ch, AFF_HIDE ) )
xREMOVE_BIT( ch->affected_by, AFF_HIDE );
if( can_use_skill( ch, number_percent( ), gsn_hide ) )
{
xSET_BIT( ch->affected_by, AFF_HIDE );
learn_from_success( ch, gsn_hide );
}
else
learn_from_failure( ch, gsn_hide );
return;
}
/*
* Contributed by Alander.
*/
void do_visible( CHAR_DATA * ch, char *argument )
{
affect_strip( ch, gsn_invis );
affect_strip( ch, gsn_mass_invis );
affect_strip( ch, gsn_sneak );
xREMOVE_BIT( ch->affected_by, AFF_HIDE );
xREMOVE_BIT( ch->affected_by, AFF_INVISIBLE );
xREMOVE_BIT( ch->affected_by, AFF_SNEAK );
send_to_char( "Ok.\n\r", ch );
return;
}
void do_recall( CHAR_DATA * ch, char *argument )
{
ROOM_INDEX_DATA *location;
location = NULL;
if( IS_PLR_FLAG( ch, PLR_ONMAP )
|| IS_ACT_FLAG( ch, ACT_ONMAP )
|| xIS_SET( ch->in_room->room_flags, ROOM_NO_RECALL )
|| IS_AFFECTED( ch, AFF_CURSE ) || ch->position == POS_FIGHTING || ch->in_room == location )
{
send_to_char( "For some strange reason... the God's forbid you from recalling.\n\r", ch );
return;
}
if( !str_cmp( argument, "clanhall" ) )
{
if( !IS_NPC( ch ) && ch->pcdata->clan )
{
location = get_room_index( ch->pcdata->clan->recall );
if( location == NULL )
return;
else
char_from_room( ch );
char_to_room( ch, location );
do_look( ch, "auto" );
return;
}
else
{
send_to_char( "You do not belong to a clan.\n\r", ch );
return;
}
}
if( !str_cmp( ch->in_room->area->filename, "raventower.are" ) )
{
location = get_room_index( 5150 );
}
else if( !str_cmp( ch->in_room->area->filename, "blacktower.are" ) )
{
location = get_room_index( 5500 );
}
else if( !str_cmp( ch->in_room->area->filename, "whitetower.are" ) )
{
location = get_room_index( 5600 );
}
else if( !str_cmp( ch->in_room->area->filename, "school.are" ) )
{
location = get_room_index( 10300 );
}
else if( !str_cmp( ch->in_room->area->filename, "dwarven.are" ) )
{
location = get_room_index( 22310 );
}
else if( !str_cmp( ch->in_room->area->filename, "gtown.are" ) )
{
location = get_room_index( 50250 );
}
else if( !str_cmp( ch->in_room->area->filename, "gyard.are" ) )
{
location = get_room_index( 50250 );
}
else if( !str_cmp( ch->in_room->area->filename, "mahntor.are" ) )
{
location = get_room_index( 50500 );
}
else if( !str_cmp( ch->in_room->area->filename, "ofcol.are" ) )
{
location = get_room_index( 50600 );
}
else if( !str_cmp( ch->in_room->area->filename, "ofcol2.are" ) )
{
location = get_room_index( 50600 );
}
else if( !str_cmp( ch->in_room->area->filename, "newthalos.are" ) )
{
location = get_room_index( 52390 );
}
else if( !str_cmp( ch->in_room->area->filename, "shadval.are" ) )
{
location = get_room_index( 52390 );
}
else if( !str_cmp( ch->in_room->area->filename, "thalos.are" ) )
{
location = get_room_index( 52390 );
}
else if( !str_cmp( ch->in_room->area->filename, "manor.are" ) )
{
location = get_room_index( 52900 );
}
else if( !str_cmp( ch->in_room->area->filename, "olympus.are" ) )
{
location = get_room_index( 52900 );
}
else if( !str_cmp( ch->in_room->area->filename, "valley.are" ) )
{
location = get_room_index( 52900 );
}
else if( !str_cmp( ch->in_room->area->filename, "canyon.are" ) )
{
location = get_room_index( 52900 );
}
else if( !str_cmp( ch->in_room->area->filename, "damara.are" ) )
{
location = get_room_index( 53150 );
}
else if( !str_cmp( ch->in_room->area->filename, "draconia.are" ) )
{
location = get_room_index( 53250 );
}
else if( !str_cmp( ch->in_room->area->filename, "arcdia.are" ) )
{
location = get_room_index( 53367 );
}
else if( !str_cmp( ch->in_room->area->filename, "armagddn.are" ) )
{
location = get_room_index( 53550 );
}
else if( !str_cmp( ch->in_room->area->filename, "roanewb.are" ) )
{
location = get_room_index( 841 );
}
else
{
location = get_room_index( ROOM_VNUM_RECALL );
}
act( AT_ACTION, "$n disappears in a swirl of smoke.", ch, NULL, NULL, TO_ROOM );
char_from_room( ch );
char_to_room( ch, location );
if( ch->mount )
{
char_from_room( ch->mount );
char_to_room( ch->mount, location );
}
act( AT_ACTION, "$n appears in the room.", ch, NULL, NULL, TO_ROOM );
do_look( ch, "auto" );
if( ch->on )
{
ch->on = NULL;
ch->position = POS_STANDING;
}
if( ch->position != POS_STANDING )
{
ch->position = POS_STANDING;
}
return;
}
void do_mount( CHAR_DATA * ch, char *argument )
{
CHAR_DATA *victim;
if( !IS_NPC( ch ) && ch->level < skill_table[gsn_mount]->skill_level[ch->class] )
{
send_to_char( "I don't think that would be a good idea...\n\r", ch );
return;
}
if( ch->mount )
{
send_to_char( "You're already mounted!\n\r", ch );
return;
}
if( ( victim = get_char_room( ch, argument ) ) == NULL )
{
send_to_char( "You can't find that here.\n\r", ch );
return;
}
if( !IS_NPC( victim ) || !xIS_SET( victim->act, ACT_MOUNTABLE ) )
{
send_to_char( "You can't mount that!\n\r", ch );
return;
}
if( xIS_SET( victim->act, ACT_MOUNTED ) )
{
send_to_char( "That mount already has a rider.\n\r", ch );
return;
}
if( victim->position < POS_STANDING )
{
send_to_char( "Your mount must be standing.\n\r", ch );
return;
}
if( victim->position == POS_FIGHTING || victim->fighting )
{
send_to_char( "Your mount is moving around too much.\n\r", ch );
return;
}
WAIT_STATE( ch, skill_table[gsn_mount]->beats );
if( can_use_skill( ch, number_percent( ), gsn_mount ) )
{
xSET_BIT( victim->act, ACT_MOUNTED );
ch->mount = victim;
act( AT_SKILL, "You mount $N.", ch, NULL, victim, TO_CHAR );
act( AT_SKILL, "$n skillfully mounts $N.", ch, NULL, victim, TO_NOTVICT );
act( AT_SKILL, "$n mounts you.", ch, NULL, victim, TO_VICT );
learn_from_success( ch, gsn_mount );
ch->position = POS_MOUNTED;
}
else
{
act( AT_SKILL, "You unsuccessfully try to mount $N.", ch, NULL, victim, TO_CHAR );
act( AT_SKILL, "$n unsuccessfully attempts to mount $N.", ch, NULL, victim, TO_NOTVICT );
act( AT_SKILL, "$n tries to mount you.", ch, NULL, victim, TO_VICT );
learn_from_failure( ch, gsn_mount );
}
return;
}
void do_dismount( CHAR_DATA * ch, char *argument )
{
CHAR_DATA *victim;
if( ( victim = ch->mount ) == NULL )
{
send_to_char( "You're not mounted.\n\r", ch );
return;
}
WAIT_STATE( ch, skill_table[gsn_mount]->beats );
if( can_use_skill( ch, number_percent( ), gsn_mount ) )
{
act( AT_SKILL, "You dismount $N.", ch, NULL, victim, TO_CHAR );
act( AT_SKILL, "$n skillfully dismounts $N.", ch, NULL, victim, TO_NOTVICT );
act( AT_SKILL, "$n dismounts you. Whew!", ch, NULL, victim, TO_VICT );
xREMOVE_BIT( victim->act, ACT_MOUNTED );
ch->mount = NULL;
ch->position = POS_STANDING;
learn_from_success( ch, gsn_mount );
}
else
{
act( AT_SKILL, "You fall off while dismounting $N. Ouch!", ch, NULL, victim, TO_CHAR );
act( AT_SKILL, "$n falls off of $N while dismounting.", ch, NULL, victim, TO_NOTVICT );
act( AT_SKILL, "$n falls off your back.", ch, NULL, victim, TO_VICT );
learn_from_failure( ch, gsn_mount );
xREMOVE_BIT( victim->act, ACT_MOUNTED );
ch->mount = NULL;
ch->position = POS_SITTING;
global_retcode = damage( ch, ch, 1, TYPE_UNDEFINED );
}
return;
}
/**************************************************************************/
/*
* Check for parry.
*/
bool check_parry( CHAR_DATA * ch, CHAR_DATA * victim )
{
int chances;
if (victim->level < skill_table[gsn_parry]->skill_level[victim->class] )
return FALSE;
if( !IS_AWAKE( victim ) )
return FALSE;
if( IS_NPC( victim ) && !xIS_SET( victim->defenses, DFND_PARRY ) )
return FALSE;
if( IS_NPC( victim ) )
{
/*
* Tuan was here. :)
*/
chances = UMIN( 20, victim->level / 1.5 );
}
else
{
if( get_eq_char( victim, WEAR_WIELD ) == NULL )
return FALSE;
chances = ( int )( LEARNED( victim, gsn_parry ) / sysdata.parry_mod );
}
/*
* Put in the call to chance() to allow penalties for misaligned
* clannies.
*/
if( !chance( victim, chances + victim->level - ch->level ) )
{
learn_from_failure( victim, gsn_parry );
return FALSE;
}
if( !IS_NPC( victim ) && !IS_SET( victim->pcdata->flags, PCFLAG_GAG ) )
/*SB*/ act( AT_SKILL, "You parry $n's attack.", ch, NULL, victim, TO_VICT );
if( !IS_NPC( ch ) && !IS_SET( ch->pcdata->flags, PCFLAG_GAG ) ) /* SB */
act( AT_SKILL, "$N parries your attack.", ch, NULL, victim, TO_CHAR );
learn_from_success( victim, gsn_parry );
return TRUE;
}
/*
* Check for dodge.
*/
bool check_dodge( CHAR_DATA * ch, CHAR_DATA * victim )
{
int chances;
if (victim->level < skill_table[gsn_dodge]->skill_level[victim->class] )
return FALSE;
if( !IS_AWAKE( victim ) )
return FALSE;
if( IS_NPC( victim ) && !xIS_SET( victim->defenses, DFND_DODGE ) )
return FALSE;
if( IS_NPC( victim ) )
chances = UMIN( 20, victim->level / 1.5 );
else
chances = ( int )( LEARNED( victim, gsn_dodge ) / sysdata.dodge_mod );
/*
* Consider luck as a factor
*/
if( !chance( victim, chances + victim->level - ch->level ) )
{
learn_from_failure( victim, gsn_dodge );
return FALSE;
}
if( !IS_NPC( victim ) && !IS_SET( victim->pcdata->flags, PCFLAG_GAG ) )
act( AT_SKILL, "You dodge $n's attack.", ch, NULL, victim, TO_VICT );
if( !IS_NPC( ch ) && !IS_SET( ch->pcdata->flags, PCFLAG_GAG ) )
act( AT_SKILL, "$N dodges your attack.", ch, NULL, victim, TO_CHAR );
learn_from_success( victim, gsn_dodge );
return TRUE;
}
bool check_tumble( CHAR_DATA * ch, CHAR_DATA * victim )
{
int chances;
if (victim->level < skill_table[gsn_tumble]->skill_level[victim->class] )
return FALSE;
if( !IS_AWAKE( victim ) )
return FALSE;
if( IS_NPC( victim ) && !xIS_SET( victim->defenses, DFND_TUMBLE ) )
return FALSE;
if( IS_NPC( victim ) )
chances = UMIN( 20, victim->level / 1.5 );
else
chances = ( int )( LEARNED( victim, gsn_tumble ) / sysdata.tumble_mod + ( get_curr_dex( victim ) - 13 ) );
if( !chance( victim, chances + victim->level - ch->level ) )
{
learn_from_failure( victim, gsn_tumble );
return FALSE;
}
if( !IS_NPC( victim ) && !IS_SET( victim->pcdata->flags, PCFLAG_GAG ) )
act( AT_SKILL, "You tumble away from $n's attack.", ch, NULL, victim, TO_VICT );
if( !IS_NPC( ch ) && !IS_SET( ch->pcdata->flags, PCFLAG_GAG ) )
act( AT_SKILL, "$N tumbles away from your attack.", ch, NULL, victim, TO_CHAR );
learn_from_success( victim, gsn_tumble );
return TRUE;
}
/* Re-worked by Sadiq to allow PCs to scribe up to 3 spells on a single *
* scroll. Second and third spells progressive increase the chance of *
* destroying the scroll. --Sadiq */
void do_scribe( CHAR_DATA * ch, char *argument )
{
OBJ_DATA *scroll;
int sn;
char buf1[MAX_STRING_LENGTH];
char buf2[MAX_STRING_LENGTH];
char buf3[MAX_STRING_LENGTH];
int mana;
if( IS_NPC( ch ) )
return;
if( !IS_NPC( ch ) && ch->level < skill_table[gsn_scribe]->skill_level[ch->class] )
{
send_to_char( "A skill such as this requires more magical ability than that of your class.\n\r", ch );
return;
}
if( argument[0] == '\0' || !str_cmp( argument, "" ) )
{
send_to_char( "Scribe what?\n\r", ch );
return;
}
if( ms_find_obj( ch ) )
return;
if( ( sn = find_spell( ch, argument, TRUE ) ) < 0 )
{
send_to_char( "You have not learned that spell.\n\r", ch );
return;
}
if( skill_table[sn]->spell_fun == spell_null )
{
send_to_char( "That's not a spell!\n\r", ch );
return;
}
if( SPELL_FLAG( skill_table[sn], SF_NOSCRIBE ) )
{
send_to_char( "You cannot scribe that spell.\n\r", ch );
return;
}
mana = IS_NPC( ch ) ? 0 : UMAX( skill_table[sn]->min_mana,
100 / ( 2 + ch->level - skill_table[sn]->skill_level[ch->class] ) );
mana *= 5;
if( !IS_NPC( ch ) && ch->mana < mana )
{
send_to_char( "You don't have enough mana.\n\r", ch );
return;
}
if( ( scroll = get_eq_char( ch, WEAR_HOLD ) ) == NULL )
{
send_to_char( "You must be holding a blank scroll to scribe it.\n\r", ch );
return;
}
if( scroll->pIndexData->vnum != OBJ_VNUM_SCROLL_SCRIBING )
{
send_to_char( "You must be holding a blank scroll to scribe it.\n\r", ch );
return;
}
if( ( scroll->value[1] != -1 ) && ( scroll->value[2] != -1 )
&& ( scroll->value[3] != -1 ) && ( scroll->pIndexData->vnum == OBJ_VNUM_SCROLL_SCRIBING ) )
{
send_to_char( "That scroll has already contains as much magic as it can hold.\n\r", ch );
return;
}
if( !process_spell_components( ch, sn ) )
{
learn_from_failure( ch, gsn_scribe );
ch->mana -= ( mana / 2 );
return;
}
if( !IS_NPC( ch ) && number_percent( ) > ch->pcdata->learned[gsn_scribe] )
{
set_char_color( AT_MAGIC, ch );
send_to_char( "The magic surges outof control and destroys the scroll!.\n\r", ch );
learn_from_failure( ch, gsn_scribe );
ch->mana -= ( mana / 2 );
extract_obj( scroll );
return;
}
if( scroll->value[1] == -1 )
{
scroll->value[1] = sn;
scroll->value[0] = ch->level;
sprintf( buf1, "magically scribed scroll" );
STRFREE( scroll->short_descr );
scroll->short_descr = STRALLOC( aoran( buf1 ) );
sprintf( buf2, "A magically scribed scroll lies in the dust." );
STRFREE( scroll->description );
scroll->description = STRALLOC( buf2 );
sprintf( buf3, "scroll scribing %s", skill_table[sn]->name );
STRFREE( scroll->name );
scroll->name = STRALLOC( buf3 );
act( AT_MAGIC, "$n magiclly scribes a scroll.", ch, NULL, NULL, TO_ROOM );
set_char_color( AT_MAGIC, ch );
ch_printf( ch, "You imbue the scroll with %s.\n\r", skill_table[sn]->name );
/*
* act( AT_MAGIC, "$n magically scribes a scroll.", ch, NULL, NULL, TO_ROOM );
*/
/*
* act( AT_MAGIC, "You magically scribe $p.", ch, NULL, NULL, TO_CHAR );
*/
learn_from_success( ch, gsn_scribe );
ch->mana -= mana;
return;
}
if( scroll->value[2] == -1 )
{
if( number_percent( ) > 80 )
{
set_char_color( AT_MAGIC, ch );
send_to_char( "The magic surges out of control and destroys the scroll!.\n\r", ch );
learn_from_failure( ch, gsn_scribe );
ch->mana -= ( mana / 2 );
extract_obj( scroll );
return;
}
if( scroll->value[0] > ch->level )
{
scroll->value[0] = ch->level;
}
scroll->value[2] = sn;
set_char_color( AT_MAGIC, ch );
ch_printf( ch, "You imbue the scroll with %s.\n\r", skill_table[sn]->name );
learn_from_success( ch, gsn_scribe );
ch->mana -= mana;
return;
}
if( scroll->value[3] == -1 )
{
if( number_percent( ) > 60 )
{
set_char_color( AT_MAGIC, ch );
send_to_char( "The magic surges outof control and destroys the scroll!.\n\r", ch );
learn_from_failure( ch, gsn_scribe );
ch->mana -= ( mana / 2 );
extract_obj( scroll );
return;
}
if( scroll->value[0] > ch->level )
{
scroll->value[0] = ch->level;
}
scroll->value[3] = sn;
set_char_color( AT_MAGIC, ch );
ch_printf( ch, "You imbue the scroll with %s.\n\r", skill_table[sn]->name );
learn_from_success( ch, gsn_scribe );
ch->mana -= mana;
return;
}
}
/*
brewing 3 spells to one vial, based on do_scribe 3 spells by sadiq
*/
void do_brew( CHAR_DATA * ch, char *argument )
{
OBJ_DATA *potion;
int sn;
char buf1[MAX_STRING_LENGTH];
char buf2[MAX_STRING_LENGTH];
char buf3[MAX_STRING_LENGTH];
int mana;
if( IS_NPC( ch ) )
return;
if( !IS_NPC( ch ) && ch->level < skill_table[gsn_brew]->skill_level[ch->class] )
{
send_to_char( "A skill such as this requires more magical ability than that of your class.\n\r", ch );
return;
}
if( argument[0] == '\0' || !str_cmp( argument, "" ) )
{
send_to_char( "brew what?\n\r", ch );
return;
}
if( ms_find_obj( ch ) )
return;
if( ( sn = find_spell( ch, argument, TRUE ) ) < 0 )
{
send_to_char( "You have not learned that spell.\n\r", ch );
return;
}
if( skill_table[sn]->spell_fun == spell_null )
{
send_to_char( "That's not a spell!\n\r", ch );
return;
}
if( SPELL_FLAG( skill_table[sn], SF_NOBREW ) )
{
send_to_char( "You cannot brew that spell.\n\r", ch );
return;
}
mana = IS_NPC( ch ) ? 0 : UMAX( skill_table[sn]->min_mana,
100 / ( 2 + ch->level - skill_table[sn]->skill_level[ch->class] ) );
mana *= 5;
if( !IS_NPC( ch ) && ch->mana < mana )
{
send_to_char( "You don't have enough mana.\n\r", ch );
return;
}
if( ( potion = get_eq_char( ch, WEAR_HOLD ) ) == NULL )
{
send_to_char( "You must be holding a blank potion to brew it.\n\r", ch );
return;
}
if( potion->pIndexData->vnum != OBJ_VNUM_FLASK_BREWING )
{
send_to_char( "You must be holding a blank potion to brew it.\n\r", ch );
return;
}
if( ( potion->value[1] != -1 ) && ( potion->value[2] != -1 )
&& ( potion->value[3] != -1 ) && ( potion->pIndexData->vnum == OBJ_VNUM_FLASK_BREWING ) )
{
send_to_char( "That potion has already contains as much magic as it can hold.\n\r", ch );
return;
}
if( !process_spell_components( ch, sn ) )
{
learn_from_failure( ch, gsn_brew );
ch->mana -= ( mana / 2 );
return;
}
if( !IS_NPC( ch ) && number_percent( ) > ch->pcdata->learned[gsn_brew] )
{
set_char_color( AT_MAGIC, ch );
send_to_char( "The magic surges outof control and destroys the potion!.\n\r", ch );
learn_from_failure( ch, gsn_brew );
ch->mana -= ( mana / 2 );
extract_obj( potion );
return;
}
if( potion->value[1] == -1 )
{
potion->value[1] = sn;
potion->value[0] = ch->level;
sprintf( buf1, "A magically brewed potion %s", skill_table[sn]->name );
STRFREE( potion->short_descr );
potion->short_descr = STRALLOC( aoran( buf1 ) );
sprintf( buf2, "A magically brewed potion lies in the dust." );
STRFREE( potion->description );
potion->description = STRALLOC( buf2 );
sprintf( buf3, "potion scribing %s", skill_table[sn]->name );
STRFREE( potion->name );
potion->name = STRALLOC( buf3 );
act( AT_MAGIC, "$n magiclly brews a potion.", ch, NULL, NULL, TO_ROOM );
set_char_color( AT_MAGIC, ch );
ch_printf( ch, "You imbue the potion with %s.\n\r", skill_table[sn]->name );
learn_from_success( ch, gsn_brew );
ch->mana -= mana;
return;
}
if( potion->value[2] == -1 )
{
if( number_percent( ) > 80 )
{
set_char_color( AT_MAGIC, ch );
send_to_char( "The magic surges out of control and destroys the potion!.\n\r", ch );
learn_from_failure( ch, gsn_brew );
ch->mana -= ( mana / 2 );
extract_obj( potion );
return;
}
if( potion->value[0] > ch->level )
{
potion->value[0] = ch->level;
}
potion->value[2] = sn;
set_char_color( AT_MAGIC, ch );
ch_printf( ch, "You imbue the potion with %s.\n\r", skill_table[sn]->name );
learn_from_success( ch, gsn_brew );
ch->mana -= mana;
return;
}
if( potion->value[3] == -1 )
{
if( number_percent( ) < 20 )
{
set_char_color( AT_MAGIC, ch );
send_to_char( "The magic surges outof control and destroys the potion!.\n\r", ch );
learn_from_failure( ch, gsn_brew );
ch->mana -= ( mana / 2 );
extract_obj( potion );
return;
}
if( potion->value[0] > ch->level )
{
potion->value[0] = ch->level;
}
potion->value[3] = sn;
set_char_color( AT_MAGIC, ch );
ch_printf( ch, "You imbue the potion with %s.\n\r", skill_table[sn]->name );
learn_from_success( ch, gsn_brew );
ch->mana -= mana;
return;
}
}
bool check_grip( CHAR_DATA * ch, CHAR_DATA * victim )
{
int schance;
if( !IS_AWAKE( victim ) )
return FALSE;
if( IS_NPC( victim ) && !xIS_SET( victim->defenses, DFND_GRIP ) )
return FALSE;
if( IS_NPC( victim ) )
schance = UMIN( 20, victim->level / 1.5 );
else
schance = ( LEARNED( victim, gsn_grip ) );
/*
* Consider luck as a factor
*/
schance += ( 2 * ( get_curr_lck( victim ) - 13 ) );
if( number_percent( ) >= schance + victim->level - ch->level )
{
learn_from_failure( victim, gsn_grip );
return FALSE;
}
else
{
act( AT_SKILL, "You evade $n's attempt to disarm you.", ch, NULL, victim, TO_VICT );
act( AT_SKILL, "$N holds $S weapon strongly, and is not disarmed.", ch, NULL, victim, TO_CHAR );
learn_from_success( victim, gsn_grip );
return TRUE;
}
}
void do_circle( CHAR_DATA * ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
OBJ_DATA *obj;
int percent;
if( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
one_argument( argument, arg );
if( ch->mount )
{
send_to_char( "You can't circle while mounted.\n\r", ch );
return;
}
if( arg[0] == '\0' )
{
send_to_char( "Circle around whom?\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( "How can you sneak up on yourself?\n\r", ch );
return;
}
if( is_safe( ch, victim, TRUE ) )
return;
if( !( obj = get_eq_char( ch, WEAR_WIELD ) ) )
{
send_to_char( "You need to wield a piercing weapon.\n\r", ch );
return;
}
if( obj->value[3] != DAM_PIERCE )
{
send_to_char( "You need to wield a piercing weapon to circle.\n\r", ch );
return;
}
if( !ch->fighting )
{
send_to_char( "You can't circle when you aren't fighting.\n\r", ch );
return;
}
if( !victim->fighting )
{
send_to_char( "You can't circle around a person who is not fighting.\n\r", ch );
return;
}
if( victim->num_fighting < 2 )
{
act( AT_PLAIN, "You can't circle around them without a distraction.", ch, NULL, victim, TO_CHAR );
return;
}
percent = number_percent( ) - ( get_curr_lck( ch ) - 16 ) + ( get_curr_lck( victim ) - 13 );
check_attacker( ch, victim );
WAIT_STATE( ch, skill_table[gsn_circle]->beats );
if( can_use_skill( ch, percent, gsn_circle ) )
{
learn_from_success( ch, gsn_circle );
act( AT_RED, "You circle around $N.", ch, NULL, victim, TO_CHAR );
act( AT_RED, "$N gets cut to ribbons by $n's circle.", ch, NULL, victim, TO_ROOM );
WAIT_STATE( ch, 2 * PULSE_VIOLENCE );
global_retcode = multi_hit( ch, victim, gsn_circle );
adjust_favor( ch, 10, 1 );
check_illegal_pk( ch, victim );
}
else
{
learn_from_failure( ch, gsn_circle );
act( AT_RED, "Your too slow to circle $N.", ch, NULL, victim, TO_CHAR );
WAIT_STATE( ch, 2 * PULSE_VIOLENCE );
global_retcode = damage( ch, victim, 0, gsn_circle );
}
return;
}
/* Berserk and HitAll. -- Altrag */
void do_berserk( CHAR_DATA * ch, char *argument )
{
short percent;
AFFECT_DATA af;
if( !ch->fighting )
{
send_to_char( "But you aren't fighting!\n\r", ch );
return;
}
if( IS_AFFECTED( ch, AFF_BERSERK ) )
{
send_to_char( "Your rage is already at its peak!\n\r", ch );
return;
}
percent = LEARNED( ch, gsn_berserk );
WAIT_STATE( ch, skill_table[gsn_berserk]->beats );
if( !chance( ch, percent ) )
{
send_to_char( "You couldn't build up enough rage.\n\r", ch );
learn_from_failure( ch, gsn_berserk );
return;
}
af.type = gsn_berserk;
/*
* Hmmm.. 10-20 combat rounds at level 50.. good enough for most mobs,
* and if not they can always go berserk again.. shrug.. maybe even
* too high. -- Altrag
*/
af.duration = number_range( ch->level / 5, ch->level * 2 / 5 );
/*
* Hmm.. you get stronger when yer really enraged.. mind over matter
* type thing..
*/
af.location = APPLY_STR;
af.modifier = 1;
af.bitvector = meb( AFF_BERSERK );
affect_to_char( ch, &af );
send_to_char( "You start to lose control..\n\r", ch );
learn_from_success( ch, gsn_berserk );
return;
}
/* External from fight.c */
ch_ret one_hit args( ( CHAR_DATA * ch, CHAR_DATA * victim, int dt ) );
void do_hitall( CHAR_DATA * ch, char *argument )
{
CHAR_DATA *vch;
CHAR_DATA *vch_next;
short nvict = 0;
short nhit = 0;
short percent;
if( xIS_SET( ch->in_room->room_flags, ROOM_SAFE ) )
{
send_to_char_color( "&BA godly force prevents you.\n\r", ch );
return;
}
if( !ch->in_room->first_person )
{
send_to_char( "There's no one else here!\n\r", ch );
return;
}
percent = LEARNED( ch, gsn_hitall );
for( vch = ch->in_room->first_person; vch; vch = vch_next )
{
vch_next = vch->next_in_room;
if( is_same_group( ch, vch ) || !is_legal_kill( ch, vch ) || !can_see( ch, vch, FALSE ) || is_safe( ch, vch, TRUE ) )
continue;
if( ++nvict > ch->level / 5 )
break;
check_illegal_pk( ch, vch );
if( chance( ch, percent ) )
{
nhit++;
global_retcode = one_hit( ch, vch, TYPE_UNDEFINED );
}
else
global_retcode = damage( ch, vch, 0, TYPE_UNDEFINED );
/*
* Fireshield, etc. could kill ch too.. :>.. -- Altrag
*/
if( global_retcode == rCHAR_DIED || global_retcode == rBOTH_DIED || char_died( ch ) )
return;
}
if( !nvict )
{
send_to_char( "There's no one else here!\n\r", ch );
return;
}
ch->move = UMAX( 0, ch->move - nvict * 3 + nhit );
if( nhit )
learn_from_success( ch, gsn_hitall );
else
learn_from_failure( ch, gsn_hitall );
return;
}
bool check_illegal_psteal( CHAR_DATA * ch, CHAR_DATA * victim )
{
if( !IS_NPC( victim ) && !IS_NPC( ch ) )
{
if( ( !IS_SET( victim->pcdata->flags, PCFLAG_DEADLY )
|| ch->level - victim->level > 10
|| !IS_SET( ch->pcdata->flags, PCFLAG_DEADLY ) )
&& ( ch->in_room->vnum < 29 || ch->in_room->vnum > 43 ) && ch != victim )
{
/*
* sprintf( log_buf, "%s illegally stealing from %s at %d",
* (IS_NPC(ch) ? ch->short_descr : ch->name),
* victim->name,
* victim->in_room->vnum );
* log_string( log_buf );
* to_channel( log_buf, CHANNEL_MONITOR, "Monitor", LEVEL_IMMORTAL );
*/
return TRUE;
}
}
return FALSE;
}
static char *dir_desc[] = {
"to the north",
"to the east",
"to the south",
"to the west",
"upwards",
"downwards",
"to the northeast",
"to the northwest",
"to the southeast",
"to the southwest",
"through the portal"
};
static char *rng_desc[] = {
"right here",
"immediately",
"nearby",
"a ways",
"a good ways",
"far",
"far off",
"very far",
"very far off",
"in the distance"
};
static void scanroom( CHAR_DATA * ch, ROOM_INDEX_DATA * room, int dir, int maxdist, int dist )
{
CHAR_DATA *tch;
EXIT_DATA *ex;
for( tch = room->first_person; tch; tch = tch->next_in_room )
{
if( can_see( ch, tch, FALSE ) && !is_ignoring( tch, ch ) )
ch_printf( ch, "%-30s : %s %s\n\r", IS_NPC( tch ) ? tch->short_descr : tch->name,
rng_desc[dist], dist == 0 ? "" : dir_desc[dir] );
}
for( ex = room->first_exit; ex; ex = ex->next )
if( ex->vdir == dir )
break;
if( !ex || ex->vdir != dir || ex->vdir == DIR_SOMEWHERE || maxdist - 1 == 0 || IS_EXIT_FLAG( ex, EX_CLOSED ) || IS_EXIT_FLAG( ex, EX_DIG ) /* || IS_EXIT_FLAG(ex, EX_FORTIFIED)
* || IS_EXIT_FLAG(ex, EX_HEAVY) || IS_EXIT_FLAG(ex, EX_MEDIUM) || IS_EXIT_FLAG(ex, EX_LIGHT)
* || IS_EXIT_FLAG(ex, EX_CRUMBLING) */ || IS_EXIT_FLAG( ex, EX_OVERLAND ) )
return;
scanroom( ch, ex->to_room, dir, maxdist - 1, dist + 1 );
}
void map_scan( CHAR_DATA * ch );
/* Scan no longer accepts a direction argument */
void do_scan( CHAR_DATA * ch, char *argument )
{
int maxdist = 1;
EXIT_DATA *ex;
maxdist = ch->level / 10;
maxdist = URANGE( 1, maxdist, 9 );
if( IS_PLR_FLAG( ch, PLR_ONMAP ) || IS_ACT_FLAG( ch, ACT_ONMAP ) )
{
map_scan( ch );
return;
}
scanroom( ch, ch->in_room, -1, 1, 0 );
for( ex = ch->in_room->first_exit; ex; ex = ex->next )
{
if( IS_EXIT_FLAG( ex, EX_DIG ) || IS_EXIT_FLAG( ex, EX_CLOSED )
/*
* || IS_EXIT_FLAG(ex, EX_FORTIFIED) || IS_EXIT_FLAG(ex, EX_HEAVY)
* || IS_EXIT_FLAG(ex, EX_MEDIUM) || IS_EXIT_FLAG(ex, EX_LIGHT)
* || IS_EXIT_FLAG(ex, EX_CRUMBLING)
*/ || IS_EXIT_FLAG( ex, EX_OVERLAND ) )
continue;
if( ex->vdir == DIR_SOMEWHERE && !IS_IMMORTAL( ch ) )
continue;
scanroom( ch, ex->to_room, ex->vdir, maxdist, 1 );
learn_from_success( ch, gsn_scan );
}
}
/* -- working on --
* Syntaxes: throw object (assumed already fighting)
* throw object direction target (all needed args for distance
* throwing)
* throw object (assumed same room throw)
void do_throw( CHAR_DATA *ch, char *argument )
{
ROOM_INDEX_DATA *was_in_room;
CHAR_DATA *victim;
OBJ_DATA *throw_obj;
EXIT_DATA *pexit;
short dir;
short dist;
short max_dist = 3;
char arg[MAX_INPUT_LENGTH];
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
argument = one_argument( argument, arg );
argument = one_argument( argument, arg1 );
argument = one_argument( argument, arg2 );
for ( throw_obj = ch->last_carrying; throw_obj;
throw_obj = throw_obj=>prev_content )
{
--- if ( can_see_obj( ch, throw_obj )
&& ( throw_obj->wear_loc == WEAR_HELD || throw_obj->wear_loc ==
WEAR_WIELDED || throw_obj->wear_loc == WEAR_DUAL_WIELDED )
&& nifty_is_name( arg, throw_obj->name ) )
break;
----
if ( can_see_obj( ch, throw_obj ) && nifty_is_name( arg, throw_obj->name )
break;
}
if ( !throw_obj )
{
send_to_char( "You aren't holding or wielding anything like that.\n\r", ch );
return;
}
----
if ( ( throw_obj->item_type != ITEM_WEAPON)
{
send_to_char("You can only throw weapons.\n\r", ch );
return;
}
----
if (get_obj_weight( throw_obj ) - ( 3 * (get_curr_str(ch) - 15) ) > 0)
{
send_to_char("That is too heavy for you to throw.\n\r", ch);
if (!number_range(0,10))
learn_from_failure( ch, gsn_throw );
return;
}
if ( ch->fighting )
victim = ch->fighting;
else
{
if ( ( ( victim = get_char_room( ch, arg1 ) ) == NULL )
&& ( arg2[0] == '\0' ) )
{
act( AT_GREY, "Throw $t at whom?", ch, obj->short_descr, NULL,
TO_CHAR );
return;
}
}
}*/
void do_slice( CHAR_DATA * ch, char *argument )
{
OBJ_DATA *corpse;
OBJ_DATA *obj;
OBJ_DATA *slice;
bool found;
char buf[MAX_STRING_LENGTH];
char buf1[MAX_STRING_LENGTH];
found = FALSE;
/*
* Noticed that it was checking gsn_kick. Bug report by Li'l Lukey
*/
if( !IS_NPC( ch ) && !IS_IMMORTAL( ch ) && ch->level < skill_table[gsn_slice]->skill_level[ch->class] )
{
send_to_char( "You are not learned in this skill.\n\r", ch );
return;
}
if( argument[0] == '\0' )
{
send_to_char( "From what do you wish to slice meat?\n\r", ch );
return;
}
if( ( obj = get_eq_char( ch, WEAR_WIELD ) ) == NULL
|| ( obj->value[3] != 1 && obj->value[3] != 2 && obj->value[3] != 3 && obj->value[3] != 11 ) )
{
send_to_char( "You need to wield a sharp weapon.\n\r", ch );
return;
}
if( ( corpse = get_obj_here( ch, argument ) ) == NULL )
{
send_to_char( "You can't find that here.\n\r", ch );
return;
}
if( corpse->item_type != ITEM_CORPSE_NPC )
{
send_to_char( "That is not a suitable source of meat.\n\r", ch );
return;
}
if( get_obj_index( OBJ_VNUM_SLICE ) == NULL )
{
bug( "Vnum 24 not found for do_slice!", 0 );
return;
}
if( !can_use_skill( ch, number_percent( ), gsn_slice ) && !IS_IMMORTAL( ch ) )
{
send_to_char( "You fail to slice the meat properly.\n\r", ch );
learn_from_failure( ch, gsn_slice ); /* Just in case they die :> */
if( number_percent( ) + ( get_curr_dex( ch ) - 13 ) < 10 )
{
act( AT_BLOOD, "You cut yourself!", ch, NULL, NULL, TO_CHAR );
damage( ch, ch, ch->level, gsn_slice );
}
return;
}
slice = create_object( get_obj_index( OBJ_VNUM_SLICE ), 0 );
sprintf( buf, "meat fresh slice %s", corpse->name );
STRFREE( slice->name );
slice->name = STRALLOC( buf );
sprintf( buf, "a slice of raw meat from %s", corpse->short_descr );
STRFREE( slice->short_descr );
slice->short_descr = STRALLOC( buf );
sprintf( buf1, "A slice of raw meat from %s lies on the ground.", corpse->short_descr );
STRFREE( slice->description );
slice->description = STRALLOC( buf1 );
act( AT_BLOOD, "$n cuts a slice of meat from $p.", ch, corpse, NULL, TO_ROOM );
act( AT_BLOOD, "You cut a slice of meat from $p.", ch, corpse, NULL, TO_CHAR );
slice->value[3] = 0;
slice->value[2] = 0;
obj_to_char( slice, ch );
obj_from_room( corpse );
learn_from_success( ch, gsn_slice );
return;
}
/*------------------------------------------------------------
* Fighting Styles - haus
*/ void do_style( CHAR_DATA * ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
/*
* char buf[MAX_INPUT_LENGTH];
* int percent;
*/
if( IS_NPC( ch ) )
return;
one_argument( argument, arg );
if( arg[0] == '\0' )
{
ch_printf_color( ch, "&wAdopt which fighting style? (current: %s&w)\n\r",
ch->style == STYLE_BERSERK ? "&Rberserk" :
ch->style == STYLE_AGGRESSIVE ? "&Raggressive" :
ch->style == STYLE_DEFENSIVE ? "&Ydefensive" :
ch->style == STYLE_EVASIVE ? "&Yevasive" : "standard" );
return;
}
if( !str_prefix( arg, "evasive" ) )
{
if( ch->level < skill_table[gsn_style_evasive]->skill_level[ch->class] )
{
send_to_char( "You have not yet learned enough to fight evasively.\n\r", ch );
return;
}
WAIT_STATE( ch, skill_table[gsn_style_evasive]->beats );
if( number_percent( ) < LEARNED( ch, gsn_style_evasive ) )
{
/*
* success
*/
if( ch->fighting )
{
ch->position = POS_EVASIVE;
learn_from_success( ch, gsn_style_evasive );
if( IS_PKILL( ch ) )
act( AT_ACTION, "$n falls back into an evasive stance.", ch, NULL, NULL, TO_ROOM );
}
ch->style = STYLE_EVASIVE;
send_to_char( "You adopt an evasive fighting style.\n\r", ch );
return;
}
else
{
/*
* failure
*/
send_to_char( "You nearly trip in a lame attempt to adopt an evasive fighting style.\n\r", ch );
learn_from_failure(ch, gsn_style_evasive);
return;
}
}
else if( !str_prefix( arg, "defensive" ) )
{
if( ch->level < skill_table[gsn_style_defensive]->skill_level[ch->class] )
{
send_to_char( "You have not yet learned enough to fight defensively.\n\r", ch );
return;
}
WAIT_STATE( ch, skill_table[gsn_style_defensive]->beats );
if( number_percent( ) < LEARNED( ch, gsn_style_defensive ) )
{
/*
* success
*/
if( ch->fighting )
{
ch->position = POS_DEFENSIVE;
learn_from_success( ch, gsn_style_defensive );
if( IS_PKILL( ch ) )
act( AT_ACTION, "$n moves into a defensive posture.", ch, NULL, NULL, TO_ROOM );
}
ch->style = STYLE_DEFENSIVE;
send_to_char( "You adopt a defensive fighting style.\n\r", ch );
return;
}
else
{
/*
* failure
*/
send_to_char( "You nearly trip in a lame attempt to adopt a defensive fighting style.\n\r", ch );
learn_from_failure(ch, gsn_style_defensive);
return;
}
}
else if( !str_prefix( arg, "standard" ) )
{
if( ch->level < skill_table[gsn_style_standard]->skill_level[ch->class] )
{
send_to_char( "You have not yet learned enough to fight in the standard style.\n\r", ch );
return;
}
WAIT_STATE( ch, skill_table[gsn_style_standard]->beats );
if( number_percent( ) < LEARNED( ch, gsn_style_standard ) )
{
/*
* success
*/
if( ch->fighting )
{
ch->position = POS_FIGHTING;
learn_from_success( ch, gsn_style_standard );
if( IS_PKILL( ch ) )
act( AT_ACTION, "$n switches to a standard fighting style.", ch, NULL, NULL, TO_ROOM );
}
ch->style = STYLE_FIGHTING;
send_to_char( "You adopt a standard fighting style.\n\r", ch );
return;
}
else
{
/*
* failure
*/
send_to_char( "You nearly trip in a lame attempt to adopt a standard fighting style.\n\r", ch );
learn_from_failure(ch, gsn_style_standard);
return;
}
}
else if( !str_prefix( arg, "aggressive" ) )
{
if( ch->level < skill_table[gsn_style_aggressive]->skill_level[ch->class] )
{
send_to_char( "You have not yet learned enough to fight aggressively.\n\r", ch );
return;
}
WAIT_STATE( ch, skill_table[gsn_style_aggressive]->beats );
if( number_percent( ) < LEARNED( ch, gsn_style_aggressive ) )
{
/*
* success
*/
if( ch->fighting )
{
ch->position = POS_AGGRESSIVE;
learn_from_success( ch, gsn_style_aggressive );
if( IS_PKILL( ch ) )
act( AT_ACTION, "$n assumes an aggressive stance.", ch, NULL, NULL, TO_ROOM );
}
ch->style = STYLE_AGGRESSIVE;
send_to_char( "You adopt an aggressive fighting style.\n\r", ch );
return;
}
else
{
/*
* failure
*/
send_to_char( "You nearly trip in a lame attempt to adopt an aggressive fighting style.\n\r", ch );
learn_from_failure(ch, gsn_style_aggressive);
return;
}
}
else if( !str_prefix( arg, "berserk" ) )
{
if( ch->level < skill_table[gsn_style_berserk]->skill_level[ch->class] )
{
send_to_char( "You have not yet learned enough to fight as a berserker.\n\r", ch );
return;
}
WAIT_STATE( ch, skill_table[gsn_style_berserk]->beats );
if( number_percent( ) < LEARNED( ch, gsn_style_berserk ) )
{
/*
* success
*/
if( ch->fighting )
{
ch->position = POS_BERSERK;
learn_from_success( ch, gsn_style_berserk );
if( IS_PKILL( ch ) )
act( AT_ACTION, "$n enters a wildly aggressive style.", ch, NULL, NULL, TO_ROOM );
}
ch->style = STYLE_BERSERK;
send_to_char( "You adopt a berserk fighting style.\n\r", ch );
return;
}
else
{
/*
* failure
*/
send_to_char( "You nearly trip in a lame attempt to adopt a berserk fighting style.\n\r", ch );
learn_from_failure(ch, gsn_style_berserk);
return;
}
}
send_to_char( "Adopt which fighting style?\n\r", ch );
return;
}
/* New check to see if you can use skills to support morphs --Shaddai */
bool can_use_skill( CHAR_DATA * ch, int percent, int gsn )
{
bool check = FALSE;
if( IS_NPC( ch ) && percent < 85 )
check = TRUE;
else if( !IS_NPC( ch ) && percent < LEARNED( ch, gsn ) )
check = TRUE;
else if( ch->morph && ch->morph->morph && ch->morph->morph->skills &&
ch->morph->morph->skills[0] != '\0' &&
is_name( skill_table[gsn]->name, ch->morph->morph->skills ) && percent < 85 )
check = TRUE;
if( ch->morph && ch->morph->morph && ch->morph->morph->no_skills &&
ch->morph->morph->no_skills[0] != '\0' && is_name( skill_table[gsn]->name, ch->morph->morph->no_skills ) )
check = FALSE;
return check;
}
/*
* Cook was coded by Blackmane and heavily modified by Shaddai
*/
void do_cook( CHAR_DATA * ch, char *argument )
{
OBJ_DATA *food, *fire;
char arg[MAX_INPUT_LENGTH];
char buf[MAX_STRING_LENGTH];
one_argument( argument, arg );
if( IS_NPC( ch ) || ch->level < skill_table[gsn_cook]->skill_level[ch->class] )
{
send_to_char( "That skill is beyond your understanding.\n\r", ch );
return;
}
if( arg[0] == '\0' )
{
send_to_char( "Cook what?\n\r", ch );
return;
}
if( ms_find_obj( ch ) )
return;
if( ( food = get_obj_carry( ch, arg ) ) == NULL )
{
send_to_char( "You do not have that item.\n\r", ch );
return;
}
if( food->item_type != ITEM_COOK )
{
send_to_char( "How can you cook that?\n\r", ch );
return;
}
if( food->value[2] > 2 )
{
send_to_char( "That is already burnt to a crisp.\n\r", ch );
return;
}
for( fire = ch->in_room->first_content; fire; fire = fire->next_content )
{
if( fire->item_type == ITEM_FIRE )
break;
}
if( !fire )
{
send_to_char( "There is no fire here!\n\r", ch );
return;
}
separate_obj( food ); /* Bug catch by Tchaika from SMAUG list */
if( number_percent( ) > LEARNED( ch, gsn_cook ) )
{
food->timer = food->timer / 2;
food->value[0] = 0;
food->value[2] = 3;
act( AT_MAGIC, "$p catches on fire burning it to a crisp!\n\r", ch, food, NULL, TO_CHAR );
act( AT_MAGIC, "$n catches $p on fire burning it to a crisp.", ch, food, NULL, TO_ROOM );
sprintf( buf, "a burnt %s", food->pIndexData->name );
STRFREE( food->short_descr );
food->short_descr = STRALLOC( buf );
sprintf( buf, "A burnt %s.", food->pIndexData->name );
STRFREE( food->description );
food->description = STRALLOC( buf );
return;
}
if( number_percent( ) > 85 )
{
food->timer = food->timer * 3;
food->value[2] += 2;
act( AT_MAGIC, "$n overcooks a $p.", ch, food, NULL, TO_ROOM );
act( AT_MAGIC, "You overcook a $p.", ch, food, NULL, TO_CHAR );
sprintf( buf, "an overcooked %s", food->pIndexData->name );
STRFREE( food->short_descr );
food->short_descr = STRALLOC( buf );
sprintf( buf, "An overcooked %s.", food->pIndexData->name );
STRFREE( food->description );
food->description = STRALLOC( buf );
}
else
{
food->timer = food->timer * 4;
food->value[0] *= 2;
act( AT_MAGIC, "$n roasts a $p.", ch, food, NULL, TO_ROOM );
act( AT_MAGIC, "You roast a $p.", ch, food, NULL, TO_CHAR );
sprintf( buf, "a roasted %s", food->pIndexData->name );
STRFREE( food->short_descr );
food->short_descr = STRALLOC( buf );
sprintf( buf, "A roasted %s.", food->pIndexData->name );
STRFREE( food->description );
food->description = STRALLOC( buf );
food->value[2]++;
}
learn_from_success( ch, gsn_cook );
}
void do_meditate( CHAR_DATA * ch, char *argument )
{
CHAR_DATA *victim;
if( IS_NPC( ch ) )
{
send_to_char( "Mobs cannot use this skill.\n\r", ch );
return;
}
if( IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You can't concentrate enough for that.\n\r", ch );
return;
}
if( ch->mount )
{
send_to_char( "You can't do that while mounted.\n\r", ch );
return;
}
if( xIS_SET( ch->in_room->room_flags, ROOM_NO_MAGIC ) )
{
set_char_color( AT_MAGIC, ch );
send_to_char( "You failed.\n\r", ch );
return;
}
if( !IS_NPC( ch ) && number_percent( ) > ch->pcdata->learned[gsn_meditate] )
{
act( AT_MAGIC, "You get distracted and stop meditating.", ch, NULL, victim, TO_CHAR );
act( AT_MAGIC, "$n is distracted by a vuage memory and stops meditating.", ch, NULL, victim, TO_ROOM );
learn_from_failure(ch, gsn_meditate);
return;
}
else
{
act( AT_MAGIC, "You meditate peacefully, collecting mana from the cosmos.", ch, NULL, victim, TO_CHAR );
act( AT_MAGIC, "$n meditates peacefully, collecting mana from the cosmos.", ch, NULL, victim, TO_ROOM );
ch->mana += ( ch->level / 2 + 20 );
learn_from_success(ch, gsn_meditate);
if( ch->mana > ch->max_mana )
ch->mana = ch->max_mana;
return;
}
}