/*___________________________________________________________________________*
)()( DalekenMUD 1.12 (C) 2000 )()(
`][' by Martin Thomson, Lee Brooks, `]['
|| Ken Herbert and David Jacques ||
|| ----------------------------------------------------------------- ||
|| Envy Diku Mud improvements copyright (C) 1994 by Michael Quan, ||
|| David Love, Guilherme 'Willie' Arnold, and Mitchell Tse. ||
|| Merc 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. ||
|| ----------------------------------------------------------------- ||
|| Any use of this software must follow the licenses of the ||
|| creators. Much time and thought has gone into this software and ||
|| you are benefitting. We hope that you share your changes too. ||
|| What goes around, comes around. ||
|| ----------------------------------------------------------------- ||
|| act_comm.c ||
|| Player communication code, channels, languages and quests. ||
*_/<>\_________________________________________________________________/<>\_*/
#include <stdarg.h>
#include "mud.h"
#include "event.h"
struct spk_type
{
const char *old;
const char *new;
};
/*
* local auction variables
*/
OBJ_DATA *auction_item = NULL;
CHAR_DATA *bidder = NULL;
CHAR_DATA *auction_owner;
int current_bid;
int auction_state;
/*
* Local functions.
*/
void quest_request args( ( CHAR_DATA *ch, CHAR_DATA *mob ) );
void quest_complete args( ( CHAR_DATA *ch, CHAR_DATA *mob ) );
void quest_info args( ( CHAR_DATA *ch ) );
void quest_identify args( ( CHAR_DATA *ch, CHAR_DATA *mob,
const char *argument ) );
void quest_improve args( ( CHAR_DATA *ch, CHAR_DATA *mob,
const char *argument ) );
bool can_speak args( ( CHAR_DATA *ch, int lang ) );
void init_auction args( ( void ) );
bool can_quit args( ( CHAR_DATA *ch ) );
DESCRIPTOR_DATA *quit_char args( ( CHAR_DATA *ch ) );
TRADE_DATA *new_trade args( ( CHAR_DATA *ch ) );
void show_trade args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
OBJ_DATA *find_trade_obj args( ( CHAR_DATA *ch, CHAR_DATA *victim,
const char *name ) );
bool check_trade args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void affect_trade args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
INTERPRETER_FUN nanny_get_name;
/*
* How to make a string look drunk by Apex <robink@htsa.hva.nl>
* Modified and enhanced by Maniac from Mythran
*/
void makedrunk( char *string, CHAR_DATA *ch )
{
char buf[MAX_STRING_LENGTH];
char temp;
char *start;
int randomnum;
int drunkpos;
int drunklevel;
int pos = 0;
/*
* Check how drunk a person is...
*/
if( IS_NPC( ch ) )
return;
if( ( drunklevel = ch->pcdata->condition[COND_DRUNK] / 3 ) > 0 )
{
start = string;
do
{
temp = UPPER( *string );
drunkpos = temp - 'A';
if( ( temp >= 'A' ) && ( temp <= 'Z' ) )
{
if( drunklevel > drunk[drunkpos].min_drunk_level )
{
randomnum =
number_range( 0, drunk[drunkpos].number_of_rep );
strcpy( &buf[pos],
drunk[drunkpos].replacement[randomnum] );
pos +=
strlen( drunk[drunkpos].replacement[randomnum] );
}
else
buf[pos++] = *string;
}
else
{
if( ( temp >= '0' ) && ( temp <= '9' ) )
{
temp = '0' + number_range( 0, 9 );
buf[pos++] = temp;
}
else if( temp == '&' )
{
buf[pos++] = *string++;
buf[pos++] = *string;
}
else
buf[pos++] = *string;
}
}
while( *string++ );
buf[pos] = '\0';
strcpy( start, buf );
}
return;
}
bool can_speak( CHAR_DATA *ch, int lang )
{
int sn;
char buf[32];
if( IS_SET( race_table[ch->race].languages, lang )
|| ch->level >= LEVEL_HERO )
return TRUE;
if( IS_NPC( ch ) )
return FALSE;
sprintf( buf, "%s language", flag_string( language_flags, &lang ) );
if( ( sn = skill_lookup( buf ) ) < 0 )
return FALSE;
if( get_success( ch, sn, 100 ) )
return TRUE;
return FALSE;
}
const char *languageshift( CHAR_DATA *ch, CHAR_DATA *victim, char *argument )
{
char *p;
char shift[ 27 ];
int i;
int length;
char buf[MAX_STRING_LENGTH];
char *bufptr;
static const struct spk_type bad_spk_table[] =
{
{ " ", " " },
{ "yes ", "yep " },
{ "no ", "naaho ", },
{ "my name is", "i calls meself"},
{ "dont you", "doncha" },
{ "are not", "aint" },
{ "have", "'av" },
{ "my", "me" },
{ "hello", "oy" },
{ "hi ", "oy " },
{ "i am", "im" },
{ "it is", "tis" },
{ "the ", "da " },
{ " the", " da" },
{ "thank", "fank" },
{ "that", "dat" },
{ "with", "wiv" },
{ "they", "day" },
{ "this", "dis" },
{ "then", "den" },
{ "there", "ver" },
{ "their", "ver" },
{ "thing", "fing" },
{ "think", "fink" },
{ "was", "woz" },
{ "would", "wud" },
{ "what", "wot" },
{ "where", "weer" },
{ "when", "wen" },
{ "are", "is" },
{ "you", "ya" },
{ "your", "yer" },
{ "dead", "ded" },
{ "kill", "smack" },
{ "food", "nosh" },
{ "blood", "blud" },
{ "vampire", "sucker" },
{ "kindred", "suckers" },
{ "fire", "hot" },
{ "dwarf", "stunty" },
{ "dwarves", "stunties" },
{ "goblin", "gobbo" },
{ "death", "def" },
{ "immune", "mune" },
{ "immunit", "munit" },
{ "children", "nippers" },
{ "childe", "nipper" },
{ "child", "nipper" },
{ "tradition", "wassname" },
{ "generation", "batch" },
{ "founded", "made" },
{ "sired", "nipped" },
{ "sire", "dad" },
{ "lineage", "istory" },
{ "recognize", "dats" },
{ "recognise", "dats" },
{ "decapitate", "headchop" },
{ "decap", "chop" },
{ "recites", "sez" },
{ "recite", "sez" },
{ "", "" }
};
static const struct spk_type archaic_spk_table[] =
{
{ " ", " ", },
{ "yes", "verily" },
{ " no", " nay" },
{ "no ", "nay " },
{ " have", " hath" },
{ "hello", "hail" },
{ "hi ", "hail " },
{ " hi", " hail" },
{ "my ", "mine " },
{ " my", " mine" },
{ "are", "art" },
{ "yours", "thine" },
{ "your", "thy" },
{ "you", "thou" },
{ "evil", "base" },
{ "clothing", "garb" },
{ "clothes", "garb" },
{ "wear", "don" },
{ "tricked", "beguiled" },
{ "trick", "beguile" },
{ "i think", "methinks" },
{ "do ", "doth " },
{ " do", " doth" },
{ "it was", "'twas" },
{ "before", "ere" },
{ "will", "wilt" },
{ "perhaps", "perchance" },
{ "cool", "fantastic" },
{ "lucky", "fortuitous" },
{ "", "" }
};
if( IS_NPC( ch ) || ch->pcdata->language == LANG_COMMON
|| !strcmp( "none", flag_string( language_flags,
&ch->pcdata->language ) ) )
return NULL;
/*
* Specialised languages, always translate.
*/
buf[0] = '\0';
bufptr = &buf[0];
if( ch->pcdata->language == LANG_BAD )
{
for( p = argument; *p; p += length )
{
for( i = 0; ( length = strlen( bad_spk_table[i].old ) ) > 0; ++i )
{
if( !str_prefix( bad_spk_table[i].old, p ) )
{
strcpy( bufptr, bad_spk_table[i].new );
bufptr += strlen( bad_spk_table[i].new );
break;
}
}
if( length == 0 )
{
length = 1;
*bufptr++ = *p;
}
}
*bufptr = '\0';
strcpy( argument, buf );
return "Bad";
}
else if( ch->pcdata->language == LANG_ARCHAIC )
{
for( p = argument; *p; p += length )
{
for( i = 0; ( length = strlen( archaic_spk_table[i].old ) ) > 0;
++i )
{
if( !str_prefix( archaic_spk_table[i].old, p ) )
{
strcpy( bufptr, archaic_spk_table[i].new );
bufptr += strlen( archaic_spk_table[i].new );
break;
}
}
if( length == 0 )
{
length = 1;
*bufptr++ = *p;
}
}
*bufptr = '\0';
strcpy( argument, buf );
return "Archaic";
}
/*
* generic languages.
*/
if( can_speak( victim, ch->pcdata->language ) )
return flag_string( language_flags, &ch->pcdata->language );
strcpy( shift, flag_string( language_flags, &ch->pcdata->language ) );
for( p = &shift[0]; *p; p++ )
if( !strchr( shift, LOWER( *p ) ) )
*p = LOWER( *p );
for( i = 0; i < 26; i++ )
{
if( !strchr( shift, 'z' - i ) )
*p++ = 'z' - i;
}
for( p = argument; *p != '\0'; p++ )
{
if( *p == '&' )
p++;
else if( *p >= 'a' && *p <= 'z' )
*p = shift[*p - 'a'];
else if( *p >= 'A' && *p <= 'Z' )
*p = shift[*p - 'A'] - 'a' + 'A';
}
return flag_string( language_flags, &ch->pcdata->language );
}
/*
* Generic channel function.
*/
void talk_channel( CHAR_DATA *ch, const char *argument, int channel,
const char *verb )
{
DESCRIPTOR_DATA *d;
char buf[MAX_INPUT_LENGTH];
char orig[MAX_INPUT_LENGTH];
char mesg[MAX_STRING_LENGTH];
const char *p;
if( argument[0] == '\0' )
{
if( IS_SET( ch->deaf, channel ) )
{
charprintf( ch, "%s channel turned on.\n\r", capitalize( verb ) );
REMOVE_BIT( ch->deaf, channel | CHANNEL_DEAF );
}
else
{
charprintf( ch, "%s channel turned off.\n\r", capitalize( verb ) );
SET_BIT( ch->deaf, channel );
}
return;
}
if( ch && !IS_NPC( ch ) && xIS_SET( ch->act, PLR_SILENCE ) )
{
sprintf( buf, "You can't %s.\n\r", verb );
send_to_char( buf, ch );
return;
}
if( ch && ( IS_AFFECTED( ch, AFF_MUTE )
|| IS_SET( race_table[ch->race].race_abilities, RACE_MUTE )
|| IS_SET( ch->in_room->room_flags, ROOM_CONE_OF_SILENCE )
|| IS_SET( ch->in_room->room_flags, ROOM_TEMP_CONE_OF_SILENCE ) ) )
{
send_to_char( "Your lips move but no sound comes out.\n\r", ch );
return;
}
if( ch && channel != CHANNEL_INFO )
REMOVE_BIT( ch->deaf, channel | CHANNEL_DEAF );
/* strip linefeed colour codes */
if( ch && get_trust( ch ) < L_JUN )
{
char *tmp;
while( ( tmp = strstr( argument, "&/" ) ) )
tmp[1] = 'n';
}
strcpy( mesg, argument );
switch( channel )
{
default:
if( ( p = languageshift( ch, ch, mesg ) ) )
sprintf( buf, "&yYou %s '$t&n&y', in %s.", verb, p );
else
sprintf( buf, "&yYou %s '$t&n&y'&n", verb );
act( buf, ch, mesg, NULL, TO_CHAR );
sprintf( buf, "&y$n %ss '$t&n&y'", verb );
break;
case CHANNEL_GRATZ:
if( ( p = languageshift( ch, ch, mesg ) ) )
sprintf( buf, "&gYou congratulate $t&n&g, in %s.", p );
else
sprintf( buf, "&gYou congratulate $t&n" );
act( buf, ch, mesg, NULL, TO_CHAR );
strcpy( buf, "&g$n congratulates $t" );
break;
case CHANNEL_SHOUT:
if( ( p = languageshift( ch, ch, mesg ) ) )
sprintf( buf, "&YYou shout '$t&n&Y', in %s.", p );
else
strcpy( buf, "&YYou shout '$t&n&Y'&n" );
act( buf, ch, mesg, NULL, TO_CHAR );
strcpy( buf, "&Y$n shouts '$t&n&Y'" );
break;
case CHANNEL_MUSIC:
if( ( p = languageshift( ch, ch, mesg ) ) )
sprintf( buf, "&mYou music '$t&n&m', in %s.", p );
else
strcpy( buf, "&mYou music '$t&n&m'&n" );
act( buf, ch, mesg, NULL, TO_CHAR );
strcpy( buf, "&m$n musics '$t&n&m'" );
break;
case CHANNEL_YELL:
if( ( p = languageshift( ch, ch, mesg ) ) )
sprintf( buf, "&rYou yell '$t&n&r', in %s.", p );
else
sprintf( buf, "&rYou yell '%s&n&r'&n", argument );
act( buf, ch, mesg, NULL, TO_CHAR );
strcpy( buf, "&r$n yells '$t&n&r'" );
break;
case CHANNEL_QUESTION:
if( ( p = languageshift( ch, ch, mesg ) ) )
sprintf( buf, "&bYou %s '$t&n&b', in %s.", verb, p );
else
sprintf( buf, "&bYou %s '$t&n&b'&n", verb );
act( buf, ch, mesg, NULL, TO_CHAR );
sprintf( buf, "&b$n %ss '$t&n&b'", verb );
break;
case CHANNEL_CLANTALK:
if( ( p = languageshift( ch, ch, mesg ) ) )
sprintf( buf, "&K%s(%s&K) '$t&n&K', in %s.", verb, PERS( ch, ch ), p );
else
sprintf( buf, "&K%s(%s&K) '$t&n&K'&n", verb, PERS( ch, ch ) );
act( buf, ch, mesg, NULL, TO_CHAR );
sprintf( buf, "&K%s($n) '$t&n&K'", verb );
break;
case CHANNEL_AUCTION:
strcpy( buf, "&rAUCTION: $t" );
act( buf, ch, argument, NULL, TO_CHAR );
break;
case CHANNEL_IMMTALK:
strcpy( buf, "&c$n: $t" );
if( ( p = languageshift( ch, ch, mesg ) ) )
act( "&c$n: $t, in $T", ch, mesg, p, TO_CHAR );
else
act( buf, ch, argument, NULL, TO_CHAR );
break;
case CHANNEL_SENIORTALK:
strcpy( buf, "&m[$n] $t" );
if( ( p = languageshift( ch, ch, mesg ) ) )
act( "&m[$n] $t, in $T", ch, mesg, p, TO_CHAR );
else
act( buf, ch, argument, NULL, TO_CHAR );
break;
case CHANNEL_INFO:
if( ch )
strcpy( buf, argument );
else
strcpy( buf, "&MINFO: $t" );
break;
}
/*
* Make the words look drunk if needed...
*/
strcpy( orig, argument );
if( ch && channel != CHANNEL_INFO )
makedrunk( orig, ch );
for( d = descriptor_list; d; d = d->next )
{
CHAR_DATA *och;
CHAR_DATA *vch;
och = d->original ? d->original : d->character;
vch = d->character;
if( !IS_SET( d->interpreter->flags, INTERPRETER_NOMESSAGE )
&& vch != ch
&& !IS_SET( och->deaf, channel )
&& !IS_SET( och->in_room->room_flags, ROOM_CONE_OF_SILENCE )
&& !IS_SET( och->in_room->room_flags, ROOM_TEMP_CONE_OF_SILENCE ) )
{
if( xIS_SET( och->act, PLR_BUSY )
|| IS_SET( och->deaf, CHANNEL_DEAF ) )
continue;
if( ( channel == CHANNEL_SENIORTALK ) && get_trust( och ) < L_SEN )
continue;
if( channel == CHANNEL_IMMTALK && get_trust( och ) <= L_HER )
continue;
if( ch && channel == CHANNEL_YELL
&& vch->in_room->area != ch->in_room->area )
continue;
if( ch && channel == CHANNEL_CLANTALK
&& och->pcdata->clan != ch->pcdata->clan )
continue;
if( ( channel == CHANNEL_SHOUT || channel == CHANNEL_YELL )
&& !IS_AWAKE( vch ) )
continue;
strcpy( mesg, orig );
if( ch && ( p = languageshift( ch, vch, mesg ) ) )
{
char *q;
q = strchr( buf, '\0' );
sprintf( q, ", in %s.", p );
act( buf, ch, mesg, vch, TO_VICT );
*q = '\0';
}
else if( ch )
act( buf, ch, argument, vch, TO_VICT );
else
act( buf, vch, argument, NULL, TO_CHAR );
}
}
return;
}
void do_auction( CHAR_DATA *ch, const char *argument )
{
char buf[MAX_INPUT_LENGTH];
char arg1[MAX_INPUT_LENGTH];
int this_bid;
OBJ_DATA *obj;
if( IS_NPC( ch ) )
{
send_to_char( "No way!\n\r", ch );
return;
}
argument = one_argument( argument, arg1 );
if( arg1[0] == '\0' && !auction_item )
{
send_to_char( "There is currently no item for auction.\n\r", ch );
send_to_char( "You can auction your own item now.\n\r", ch );
return;
}
if( arg1[0] == '\0' && auction_item )
{
send_to_char( "The item currently up for auction is:\n\r", ch );
charprintf( ch, "Name: %s \n\rLevel: %3d\n\r",
auction_item->short_descr, auction_item->level );
charprintf( ch, "Item put up by %s.\n\r", PERS( auction_owner, ch ) );
if( bidder )
charprintf( ch, "The current bid is %d gold from %s.\n\r",
current_bid, bidder->name );
else
charprintf( ch, "The reserve is %d gold.\n\r", current_bid );
return;
}
if( auction_item && ( !str_cmp( arg1, "bid" ) || !str_cmp( arg1, "bet" ) ) )
{
if( argument[0] == '\0' || !is_number_special( argument ) )
{
send_to_char( "Try bidding a number next time, eh?\n\r", ch );
return;
}
this_bid = atoi_special( argument );
if( this_bid > ch->gold )
{
send_to_char( "You don't have enough gold for that bid.\n\r", ch );
return;
}
if( this_bid < current_bid + 100 )
{
send_to_char( "You must bid at least 100 over the current bid.\n\r", ch );
return;
}
if( ch == auction_owner )
{
send_to_char( "You can't bid on your own item.\n\r", ch );
return;
}
if( ch == bidder )
{
send_to_char( "Don't worry, you allready have the bid.\n\r", ch );
return;
}
bidder = ch;
current_bid = this_bid;
auction_state = 0;
sprintf( buf, "%s bids %d on %s.", ch->name,
this_bid, auction_item->short_descr );
talk_channel( ch, buf, CHANNEL_AUCTION, "auction" );
return;
}
if( auction_item )
{
send_to_char( "Sorry, you can't auction yet.\n\r", ch );
return;
}
obj = get_obj_carry( ch, arg1 );
if( !obj )
{
send_to_char( "You can't auction something you don't have.\n\r", ch );
return;
}
if( obj->wear_loc != WEAR_NONE )
{
send_to_char( "I would suggest removing it first.\n\r", ch );
return;
}
if( !can_drop_obj( ch, obj ) )
{
send_to_char( "You can't let go of it!\n\r", ch );
return;
}
switch( obj->item_type )
{
case ITEM_KEY:
case ITEM_MONEY:
case ITEM_TREASURE:
case ITEM_TRASH:
case ITEM_CORPSE_PC:
case ITEM_CORPSE_NPC:
case ITEM_FOOD:
charprintf( ch, "You can't auction %ss.\n\r",
flag_string( type_flags, &obj->item_type ) );
return;
default:
break;
}
if( is_number_special( argument ) )
current_bid = UMAX( 0, atoi_special( argument ) );
else
current_bid = 0;
obj_from_char( obj );
auction_item = obj;
auction_owner = ch;
bidder = NULL;
auction_state = 0;
if( current_bid )
sprintf( buf, "%s puts %s up for sale, with a reserve of %d.",
ch->name, obj->short_descr, current_bid );
else
sprintf( buf, "%s puts %s up for sale.",
ch->name, obj->short_descr );
talk_channel( ch, buf, CHANNEL_AUCTION, "auction" );
return;
}
void init_auction( )
{
bidder = NULL;
auction_owner = NULL;
auction_item = NULL;
auction_state = -1;
current_bid = 0;
return;
}
void update_auction( )
{
char buf[100];
buf[0] = '\0';
switch( ++auction_state )
{
default:
case 0:
auction_state = -1;
break;
case 1:
wiznet( auction_owner, WIZ_TICKS, 0, "Auction tick (going zero)." );
return;
case 2:
sprintf( buf, "%s going once.", auction_item->short_descr );
break;
case 3:
sprintf( buf, "%s going twice.", auction_item->short_descr );
break;
case 4:
if( bidder && auction_item )
{
if( bidder->gold >= current_bid )
{
sprintf( buf, "%s sold to %s for %d gold.",
auction_item->short_descr, bidder->name, current_bid );
talk_channel( auction_owner, buf, CHANNEL_AUCTION, "auction" );
act( "The auctioneer appears before you and hands you $p.",
bidder, auction_item, NULL, TO_CHAR );
act( "The auctioner appears before $n and hands $m $p.",
bidder, auction_item, NULL, TO_ROOM );
bidder->gold -= current_bid;
auction_owner->gold += current_bid;
obj_to_char( auction_item, bidder );
init_auction( );
}
else
{
talk_channel( auction_owner,
"Current bid can't be met, the auction will continue.",
CHANNEL_AUCTION, "auction" );
current_bid /= 2;
bidder = NULL;
auction_state = 0;
sprintf( buf, "The bid is now halved to %d.", current_bid );
}
}
else
{
sprintf( buf, "No bids for %s, item will be returned to owner.",
auction_item->short_descr );
talk_channel( auction_owner, buf, CHANNEL_AUCTION, "auction" );
obj_to_char( auction_item, auction_owner );
init_auction( );
}
}
if( auction_state >= 0 )
talk_channel( auction_owner, buf, CHANNEL_AUCTION, "auction" );
return;
}
void do_deaf( CHAR_DATA *ch, const char *argument )
{
if( IS_SET( ch->deaf, CHANNEL_DEAF ) )
{
send_to_char( "You no longer ignore channels.\n\r", ch );
REMOVE_BIT( ch->deaf, CHANNEL_DEAF );
}
else
{
SET_BIT( ch->deaf, CHANNEL_DEAF );
send_to_char( "You now ignore all channels.\n\r", ch );
}
}
void do_chat( CHAR_DATA *ch, const char *argument )
{
talk_channel( ch, argument, CHANNEL_CHAT, "chat" );
return;
}
void do_clantalk( CHAR_DATA *ch, const char *argument )
{
if( !is_clan( ch ) )
{
send_to_char( "You belong to neither clan, guild nor order.\n\r", ch );
return;
}
talk_channel( ch, argument, CHANNEL_CLANTALK,
flag_string( clan_type_flags, &ch->pcdata->clan->clan_type ) );
return;
}
/*
* Alander's new channels.
*/
void do_music( CHAR_DATA *ch, const char *argument )
{
talk_channel( ch, argument, CHANNEL_MUSIC, "music" );
return;
}
void do_question( CHAR_DATA *ch, const char *argument )
{
talk_channel( ch, argument, CHANNEL_QUESTION, "question" );
return;
}
void do_answer( CHAR_DATA *ch, const char *argument )
{
talk_channel( ch, argument, CHANNEL_QUESTION, "answer" );
return;
}
void do_shout( CHAR_DATA *ch, const char *argument )
{
talk_channel( ch, argument, CHANNEL_SHOUT, "shout" );
WAIT_STATE( ch, 3 * PULSE_PER_SECOND );
return;
}
void do_yell( CHAR_DATA *ch, const char *argument )
{
talk_channel( ch, argument, CHANNEL_YELL, "yell" );
return;
}
void do_gratz( CHAR_DATA *ch, const char *argument )
{
talk_channel( ch, argument, CHANNEL_GRATZ, "congratulate" );
return;
}
void do_immtalk( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *rch;
rch = get_char( ch );
if( !authorized( rch, "immtalk" ) )
return;
talk_channel( ch, argument, CHANNEL_IMMTALK, "immtalk" );
return;
}
void do_seniortalk( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *rch;
rch = get_char( ch );
if( !authorized( rch, "seniortalk" ) )
return;
talk_channel( ch, argument, CHANNEL_SENIORTALK, "seniortalk" );
return;
}
void do_say( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *vch;
OBJ_DATA *obj;
const char *keyword;
const char *p;
char arg[MAX_INPUT_LENGTH];
char trig[MAX_INPUT_LENGTH];
char buf[MAX_INPUT_LENGTH];
char mesg[MAX_STRING_LENGTH];
if( argument[0] == '\0' )
{
send_to_char( "Say what?\n\r", ch );
return;
}
if( IS_AFFECTED( ch, AFF_MUTE )
|| IS_SET( race_table[ch->race].race_abilities, RACE_MUTE )
|| IS_SET( ch->in_room->room_flags, ROOM_CONE_OF_SILENCE )
|| IS_SET( ch->in_room->room_flags, ROOM_TEMP_CONE_OF_SILENCE ) )
{
send_to_char( "Your lips move but no sound comes out.\n\r", ch );
return;
}
if( !IS_AWAKE( ch ) )
{
send_to_char( "You mumble something in your sleep.\n\r", ch );
send_to_char( "&cYou say 'MMumble MUMBLE mumph mrr'&n\n\r", ch );
act( "&c$n says 'MMumble MUMBLE mumph mrr'", ch, NULL, NULL, TO_ROOM );
return;
}
p = strchr( argument, '\0' ) - 1;
switch( *p-- )
{
case '?':
keyword = "ask";
break;
case ')':
if( *p == ':' )
keyword = "smile";
else if( *p-- == '-' && *p == ':' )
keyword = "smile";
else
keyword = "say";
break;
case '(':
if( *p == ':' )
keyword = "frown";
else if( *p-- == '-' && *p == ':' )
keyword = "frown";
else
keyword = "says";
break;
case '!':
keyword = "exclaim";
break;
default:
keyword = "say";
break;
}
strcpy( arg, argument );
strcpy( mesg, argument );
makedrunk( mesg, ch );
REMOVE_BIT( SysInfo->flags, SYSINFO_ACT_TRIGGER );
if( ( p = languageshift( ch, ch, mesg ) ) )
{
sprintf( buf, "&cYou %s '$t&n&c', in %s.", keyword, p );
act( buf, ch, mesg, NULL, TO_CHAR );
}
else
act( "&cYou $t '$T&n&c'&n", ch, keyword, mesg, TO_CHAR );
kill_colour( trig, arg );
for( vch = ch->in_room->people; vch; vch = vch->next_in_room )
{
const char *p;
if( vch->deleted || !IS_AWAKE( vch ) || vch == ch )
continue;
strcpy( mesg, arg );
REMOVE_BIT( SysInfo->flags, SYSINFO_ACT_TRIGGER );
if( ( p = languageshift( ch, vch, mesg ) ) )
sprintf( buf, "&c$n %ss '$t&n&c', in %s.", keyword, p );
else
sprintf( buf, "&c$n %ss '$t&n&c'", keyword );
act( buf, ch, mesg, vch, TO_VICT );
if( !IS_NPC( vch ) )
continue;
if( IS_SET( spec_table[vch->spec_fun].usage, SPEC_TELL )
&& ( *spec_table[vch->spec_fun].spec_fun )
( vch, ch, SPEC_TELL, (void *)argument ) )
continue;
if( xIS_SET( vch->pIndexData->progtypes, SPEECH_PROG ) )
mprog_wordlist_check( trig, vch, ch, NULL, NULL, SPEECH_PROG );
}
if( xIS_SET( ch->in_room->progtypes, SPEECH_PROG ) )
rprog_wordlist_check( trig, ch->in_room, ch, NULL, NULL, SPEECH_PROG );
for( obj = ch->in_room->contents; obj; obj = obj->next_content )
if( !obj->deleted && xIS_SET( obj->pIndexData->progtypes,
SPEECH_PROG ) )
oprog_wordlist_check( trig, ch, obj, NULL, SPEECH_PROG );
return;
}
void do_tell( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *victim;
char arg[MAX_INPUT_LENGTH];
int position;
if( IS_AFFECTED( ch, AFF_MUTE )
|| IS_SET( race_table[ch->race].race_abilities, RACE_MUTE )
|| IS_SET( ch->in_room->room_flags, ROOM_CONE_OF_SILENCE )
|| IS_SET( ch->in_room->room_flags, ROOM_TEMP_CONE_OF_SILENCE ) )
{
send_to_char( "Your lips move but no sound comes out.\n\r", ch );
return;
}
argument = one_argument( argument, arg );
/*
* Can tell to PC's anywhere, but NPC's only in same room.
* -- Furey
*/
if( !( victim = get_char_world( ch, arg ) )
|| ( IS_NPC( victim ) && victim->in_room != ch->in_room ) )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
if( ( !IS_NPC( ch ) && ( xIS_SET( ch->act, PLR_SILENCE )
|| xIS_SET( ch->act, PLR_NO_TELL ) ) )
|| IS_SET( victim->in_room->room_flags, ROOM_CONE_OF_SILENCE )
|| IS_SET( victim->in_room->room_flags, ROOM_TEMP_CONE_OF_SILENCE ) )
{
send_to_char( "Your message didn't get through.\n\r", ch );
return;
}
if( !victim->desc )
{
if( IS_SET( spec_table[victim->spec_fun].usage, SPEC_TELL )
&& ( *spec_table[victim->spec_fun].spec_fun )
( victim, ch, SPEC_TELL, (void *)argument ) )
act( "&BYou tell $N '$t&n&B'&b", ch, argument, victim, TO_CHAR );
else
act( "$N is link dead.", ch, 0, victim, TO_CHAR );
return;
}
if( arg[0] == '\0' || argument[0] == '\0' )
{
send_to_char( "Tell whom what?\n\r", ch );
return;
}
strcpy( arg, argument );
makedrunk( arg, ch );
if( !IS_IMMORTAL( ch ) && !IS_AWAKE( victim ) )
{
act( "FYI, $E is currently asleep.", ch, NULL, victim, TO_CHAR );
act( "&BYou try to tell $N '$t&B'&n", ch, arg, victim, TO_CHAR );
position = victim->position;
victim->position = POS_STANDING;
act( "&BYou dream of $n coming and telling you '$t&B'&n", ch, arg, victim, TO_VICT );
victim->position = position;
}
else
{
act( "&BYou tell $N '$t&n&B'&b", ch, arg, victim, TO_CHAR );
position = victim->position;
victim->position = POS_STANDING;
act( "&B$n tells you '$t&n&B'&n", ch, arg, victim, TO_VICT );
victim->position = position;
}
victim->reply = ch;
if( xIS_SET( victim->act, PLR_AFK ) )
act( "&gJust so you know, $E is AFK.&n", ch, NULL, victim, TO_CHAR );
if( xIS_SET( victim->act, PLR_BUSY ) )
act( "&gJust so you know, $E is &nBUSY&g.&n", ch, NULL, victim, TO_CHAR );
return;
}
void do_reply( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *victim;
int position;
char buf[MAX_INPUT_LENGTH];
if( IS_AFFECTED( ch, AFF_MUTE )
|| IS_SET( race_table[ch->race].race_abilities, RACE_MUTE )
|| IS_SET( ch->in_room->room_flags, ROOM_CONE_OF_SILENCE )
|| IS_SET( ch->in_room->room_flags, ROOM_TEMP_CONE_OF_SILENCE ) )
{
send_to_char( "Your lips move but no sound comes out.\n\r", ch );
return;
}
if( !( victim = ch->reply ) )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
if( ( !IS_NPC( ch ) && ( xIS_SET( ch->act, PLR_SILENCE )
|| xIS_SET( ch->act, PLR_NO_TELL ) ) )
|| IS_SET( victim->in_room->room_flags, ROOM_CONE_OF_SILENCE )
|| IS_SET( victim->in_room->room_flags, ROOM_TEMP_CONE_OF_SILENCE ) )
{
send_to_char( "Your message didn't get through.\n\r", ch );
return;
}
if( argument[0] == '\0' )
{
send_to_char( "Reply what?\n\r", ch );
return;
}
if( !victim->desc )
{
act( "$N is link dead.", ch, 0, victim, TO_CHAR );
return;
}
strcpy( buf, argument );
makedrunk( buf, ch );
if( !IS_IMMORTAL( ch ) && !IS_AWAKE( victim ) )
{
act( "FYI, $E is currently asleep.", ch, 0, victim, TO_CHAR );
act( "&BYou try to tell $N '$t&B'&n", ch, buf, victim, TO_CHAR );
position = victim->position;
victim->position = POS_STANDING;
act( "&BYou dream of $n coming and telling you '$t&B'&n", ch, buf, victim, TO_VICT );
victim->position = position;
}
else
{
act( "&BYou tell $N '$t&n&B'&b", ch, buf, victim, TO_CHAR );
position = victim->position;
victim->position = POS_STANDING;
act( "&B$n tells you '$t&n&B'&n", ch, buf, victim, TO_VICT );
victim->position = position;
}
victim->reply = ch;
if( xIS_SET( victim->act, PLR_AFK ) )
act( "Just so you know, $E is AFK.", ch, NULL, victim, TO_CHAR );
return;
}
void do_emote( CHAR_DATA *ch, const char *argument )
{
char buf[MAX_STRING_LENGTH];
char *plast;
if( !IS_NPC( ch ) && xIS_SET( ch->act, PLR_NO_EMOTE ) )
{
send_to_char( "You can't show your emotions.\n\r", ch );
return;
}
if( argument[0] == '\0' )
{
send_to_char( "Emote what?\n\r", ch );
return;
}
strcpy( buf, argument );
plast = strchr( argument, '\0' ) - 1;
if( isalpha( *plast ) )
strcat( buf, "." );
REMOVE_BIT( SysInfo->flags, SYSINFO_ACT_TRIGGER );
act( "&y$n $T", ch, NULL, buf, TO_ROOM );
REMOVE_BIT( SysInfo->flags, SYSINFO_ACT_TRIGGER );
act( "&y$n $T", ch, NULL, buf, TO_CHAR );
return;
}
void do_bug( CHAR_DATA *ch, const char *argument )
{
if( argument[0] == '\0' )
{
send_to_char( "The Implementors look at you quizzically.\n\r", ch );
return;
}
append_file( ch, BUG_FILE, argument );
send_to_char( "Ok. Thanks.\n\r", ch );
return;
}
void do_idea( CHAR_DATA *ch, const char *argument )
{
if( argument[0] == '\0' )
{
send_to_char( "The Implementors look at you quizzically.\n\r", ch );
return;
}
append_file( ch, IDEA_FILE, argument );
send_to_char( "Ok. Thanks.\n\r", ch );
return;
}
void do_typo( CHAR_DATA *ch, const char *argument )
{
if( argument[0] == '\0' )
{
send_to_char( "The Implementors look at you quizzically.\n\r", ch );
return;
}
append_file( ch, TYPO_FILE, argument );
send_to_char( "Ok. Thanks.\n\r", ch );
return;
}
void do_qui( CHAR_DATA *ch, const char *argument )
{
send_to_char( "If you want to QUIT, you have to spell it out.\n\r", ch );
return;
}
bool can_quit( CHAR_DATA *ch )
{
if( IS_NPC( ch ) )
return FALSE;
if( IS_SWITCHED( ch ) )
{
send_to_char( "You can't quit until you are back in your own body.\n\r", ch );
return FALSE;
}
if( xIS_SET( ch->act, PLR_BATTLE ) )
{
send_to_char( "Not right in the middle of a battle!\n\r", ch );
return FALSE;
}
if( ch == auction_owner || ch == bidder )
{
send_to_char(
"You can't quit while participating in an auction.\n\r", ch );
return FALSE;
}
if( ch->position == POS_FIGHTING )
{
send_to_char( "No way! You are fighting.\n\r", ch );
return FALSE;
}
if( ch->position < POS_STUNNED )
{
send_to_char( "You're not DEAD yet.\n\r", ch );
return FALSE;
}
return TRUE;
}
DESCRIPTOR_DATA *quit_char( CHAR_DATA *ch )
{
DESCRIPTOR_DATA *d;
OBJ_DATA *obj, *obj_next;
if( ch->pcdata->quest->type != QUEST_NONE )
{
ch->pcdata->quest->type = QUEST_NONE;
ch->pcdata->quest->time = 30;
}
if( ch->class == CLASS_BUILDER )
do_asave( ch, "changed" );
if( ch->desc && ch->desc->pString )
string_add( ch, "@" );
if( ch->pcdata->trade )
do_trade( ch, "withdraw" );
do_call( ch, "all" );
for( obj = ch->carrying; obj; obj = obj_next )
{
obj_next = obj->next_content;
if( get_trust( ch ) < obj->level - 5 )
{
act( "$p drops to the ground.", ch, obj, NULL, TO_ROOM );
obj_from_char( obj );
obj_to_room( obj, ch->in_room );
}
}
do_quote( ch, "" );
send_to_char( "\n\r", ch );
act( "$n has left the game.", ch, NULL, NULL, TO_ROOM );
sprintf( log_buf, "%s has quit.", ch->name );
log_string( log_buf );
wiznet( ch, WIZ_LOGINS, get_trust( ch ), log_buf );
if( !IS_IMMORTAL( ch ) )
talk_channel( NULL, log_buf, CHANNEL_INFO, "INFO" );
if( xIS_SET( ch->act, PLR_VT100 ) )
send_to_char( VT_RESET_TERMINAL VT_SETWIN_CLEAR, ch );
write_to_descriptor_nice( ch->desc );
/*
* After extract_char the ch is no longer valid!
*/
save_char_obj( ch );
d = ch->desc;
extract_char( ch, TRUE );
return d;
}
void do_quit( CHAR_DATA *ch, const char *argument )
{
DESCRIPTOR_DATA *d;
if( !can_quit( ch ) )
return;
d = quit_char( ch );
if( d )
close_socket( d );
return;
}
void do_save( CHAR_DATA *ch, const char *argument )
{
if( IS_NPC( ch ) )
return;
if( ch->level < SysInfo->saveat )
{
charprintf( ch, "You must get to level %d to be able to save.\n\r",
SysInfo->saveat );
return;
}
save_char_obj( ch );
send_to_char( "Ok.\n\r", ch );
return;
}
void do_follow( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *victim;
if( argument[0] == '\0' )
{
send_to_char( "Follow whom?\n\r", ch );
return;
}
if( !( victim = get_char_room( ch, argument ) ) )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
if( IS_AFFECTED( ch, AFF_CHARM ) && ch->master )
{
act( "But you'd rather follow $N!", ch, NULL, ch->master, TO_CHAR );
return;
}
if( victim == ch )
{
if( !ch->master )
{
send_to_char( "You already follow yourself.\n\r", ch );
return;
}
stop_follower( ch );
return;
}
if( ch->master )
stop_follower( ch );
add_follower( ch, victim );
return;
}
void add_follower( CHAR_DATA *ch, CHAR_DATA *master )
{
if( ch->master )
{
bug( "Add_follower: non-null master." );
return;
}
ch->master = master;
ch->leader = NULL;
if( can_see( master, ch ) )
act( "$n now follows you.", ch, NULL, master, TO_VICT );
act( "You now follow $N.", ch, NULL, master, TO_CHAR );
return;
}
void stop_follower( CHAR_DATA *ch )
{
if( !ch->master )
{
bug( "Stop_follower: null master." );
return;
}
if( IS_AFFECTED( ch, AFF_CHARM ) )
{
xREMOVE_BIT( ch->affected_by, AFF_CHARM );
affect_strip( ch, gsn_charm_person );
affect_strip( ch, gsn_domination );
}
if( can_see( ch->master, ch ) )
act( "$n stops following you.", ch, NULL, ch->master, TO_VICT );
act( "You stop following $N.",
ch, NULL, ch->master, TO_CHAR );
ch->master = NULL;
ch->leader = NULL;
return;
}
void die_follower( CHAR_DATA *ch, char *name )
{
CHAR_DATA *fch;
if( ch->master )
stop_follower( ch );
ch->leader = NULL;
for( fch = char_list; fch; fch = fch->next )
{
if( fch->deleted )
continue;
if( fch->master == ch )
stop_follower( fch );
if( fch->leader == ch )
fch->leader = NULL;
if( fch->tracking == ch )
{
send_to_char(
"The trail goes cold and you lose track of your quarry.\n\r",
fch );
fch->tracking = NULL;
}
}
return;
}
void do_order( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *victim;
CHAR_DATA *och;
CHAR_DATA *och_next;
char arg[MAX_INPUT_LENGTH];
bool found;
bool fAll;
argument = one_argument( argument, arg );
if( arg[0] == '\0' || argument[0] == '\0' )
{
send_to_char( "Order whom to do what?\n\r", ch );
return;
}
if( IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "You feel like taking, not giving, orders.\n\r", ch );
return;
}
if( !str_cmp( arg, "all" ) )
{
fAll = TRUE;
victim = NULL;
}
else
{
fAll = FALSE;
if( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
if( victim == ch )
{
send_to_char( "Aye aye, right away!\n\r", ch );
return;
}
if( !IS_AFFECTED( victim, AFF_CHARM ) || victim->master != ch )
{
send_to_char( "Do it yourself!\n\r", ch );
return;
}
}
found = FALSE;
for( och = ch->in_room->people; och; och = och_next )
{
och_next = och->next_in_room;
if( och->deleted )
continue;
if( IS_AFFECTED( och, AFF_CHARM )
&& och->master == ch
&& ( fAll || och == victim ) )
{
found = TRUE;
act( "$n orders you to '$t'.", ch, argument, och, TO_VICT );
interpret( och, argument );
}
}
if( found )
send_to_char( "Ok.\n\r", ch );
else
send_to_char( "You have no followers here.\n\r", ch );
return;
}
void do_group( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *victim;
char tmp[MAX_INPUT_LENGTH];
const char *pos_table[] =
{ "&rDEAD!&g", "&rMortally Wounded!&g", "Incapacitated.",
"Stunned.", "Sleeping.", "Meditating.", "Resting.",
"Sitting.", "Prone.", "Prone.", "Fighting!", "Standing.", "" };
if( argument[0] == '\0' )
{
CHAR_DATA *gch;
CHAR_DATA *leader;
leader = ( ch->leader ) ? ch->leader : ch;
charprintf( ch, "&B%s&n&B's group:&n\n\r", PERS( leader, ch ) );
for( gch = char_list; gch; gch = gch->next )
{
int i;
int mm = 0;
if( gch->deleted || !is_same_group( gch, ch ) )
continue;
for( i = 0; i < MAGIC_MAX; ++i )
mm += get_max_mana( gch, i );
charprintf( ch, "&b[&c%2d %s&b]&g %s&g %4d/%4d hp "
"%4d/%4d mana %4d/%4d mv\n\r",
gch->level,
IS_NPC( gch ) ? "Mob"
: (char *)class_table[gch->class].who_name,
colour_strpad( tmp, PERS( gch, ch ), 18 ),
gch->hit, get_max_hit( gch ),
total_mana( gch->mana ), mm,
gch->move, get_max_move( gch ) );
charprintf( ch, "\t\t\t[%d xptnl] Position: %s&n\n\r",
gch->exp / 100,
pos_table[gch->position] );
}
return;
}
/* a neat little shortcut */
else if( !str_cmp( argument, "all" ) )
{
for( victim = ch->in_room->people; victim; victim = victim->next_in_room )
{
if( victim->master != ch || victim->leader == ch
|| !can_see( ch, victim ) )
continue;
victim->leader = ch;
act( "$N joins your group.", ch, NULL, victim, TO_CHAR );
act( "You join $o group.", ch, NULL, victim, TO_VICT );
act( "$N joins $o group.", ch, NULL, victim, TO_NOTVICT );
}
send_to_char( "&gEveryone that follows you is now in your group.&n\n\r",
ch );
return;
}
if( !( victim = get_char_room( ch, argument ) ) )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
/*
* Disband the group.
* ?? Should we check that ch can see victim ??
*/
if( victim == ch )
{
for( victim = char_list; victim; victim = victim->next )
{
if( victim->leader == ch || victim->master == ch )
stop_follower( victim );
}
act( "You have disbanded your group.", ch, NULL, NULL, TO_CHAR );
act( "$n has disbanded $s group.", ch, NULL, NULL, TO_ROOM );
return;
}
if( ch->master || ( ch->leader && ch->leader != ch ) )
{
send_to_char( "But you are following someone else!\n\r", ch );
return;
}
if( victim->master != ch && ch != victim )
{
act( "$N isn't following you.", ch, NULL, victim, TO_CHAR );
return;
}
if( is_same_group( victim, ch ) && ch != victim )
{
victim->leader = NULL;
act( "You remove $N from your group.", ch, NULL, victim, TO_CHAR );
act( "$n removes you from $s group.", ch, NULL, victim, TO_VICT );
act( "$n removes $N from $s group.", ch, NULL, victim, TO_NOTVICT );
return;
}
victim->leader = ch;
act( "$N joins your group.", ch, NULL, victim, TO_CHAR );
act( "You join $o group.", ch, NULL, victim, TO_VICT );
act( "$N joins $o group.", ch, NULL, victim, TO_NOTVICT );
return;
}
/*
* 'Split' originally by Gnort, God of Chaos.
*/
void do_split( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *gch;
char buf[MAX_STRING_LENGTH];
char arg[MAX_INPUT_LENGTH];
int members;
int amount;
int share;
int extra;
one_argument( argument, arg );
if( arg[0] == '\0' )
{
send_to_char( "Split how much?\n\r", ch );
return;
}
amount = atoi_special( arg );
if( amount < 0 )
{
send_to_char( "Your group wouldn't like that.\n\r", ch );
return;
}
if( amount == 0 )
{
send_to_char( "You hand out zero coins, but no one notices.\n\r", ch );
return;
}
if( ch->gold < amount )
{
send_to_char( "You don't have that much gold.\n\r", ch );
return;
}
members = 0;
for( gch = ch->in_room->people; gch; gch = gch->next_in_room )
{
if( gch->deleted )
continue;
if( is_same_group( gch, ch ) )
members++;
}
if( members < 2 )
{
if( !strcmp( argument, AUTOLOOK ) )
send_to_char( "Just keep it all.\n\r", ch );
return;
}
share = amount / members;
extra = amount % members;
if( share == 0 )
{
send_to_char( "Don't even bother, cheapskate.\n\r", ch );
return;
}
ch->gold -= amount;
ch->gold += share + extra;
charprintf( ch,
"&yYou split %d gold coins. Your share is %d gold coins.&n\n\r",
amount, share + extra );
sprintf( buf, "&y$n splits %d gold coins. Your share is %d gold coins.",
amount, share );
for( gch = ch->in_room->people; gch; gch = gch->next_in_room )
{
if( gch->deleted )
continue;
if( gch != ch && is_same_group( gch, ch ) )
{
act( buf, ch, NULL, gch, TO_VICT );
gch->gold += share;
}
}
return;
}
void do_gtell( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *gch;
char orig[MAX_INPUT_LENGTH];
char mesg[MAX_STRING_LENGTH];
if( argument[0] == '\0' )
{
send_to_char( "Tell your group what?\n\r", ch );
return;
}
if( IS_AFFECTED( ch, AFF_MUTE )
|| IS_SET( race_table[ch->race].race_abilities, RACE_MUTE )
|| IS_SET( ch->in_room->room_flags, ROOM_CONE_OF_SILENCE )
|| IS_SET( ch->in_room->room_flags, ROOM_TEMP_CONE_OF_SILENCE ) )
{
send_to_char( "Your lips move but no sound comes out.\n\r", ch );
return;
}
if( xIS_SET( ch->act, PLR_NO_TELL ) )
{
send_to_char( "Your message didn't get through!\n\r", ch );
return;
}
strcpy( orig, argument );
makedrunk( orig, ch );
for( gch = char_list; gch; gch = gch->next )
{
strcpy( mesg, argument );
if( is_same_group( gch, ch )
&& !IS_SET( gch->in_room->room_flags, ROOM_CONE_OF_SILENCE )
&& !IS_SET( gch->in_room->room_flags, ROOM_TEMP_CONE_OF_SILENCE )
&& !IS_SET( race_table[gch->race].race_abilities, RACE_MUTE )
&& !IS_AFFECTED( gch, AFF_MUTE ) )
{
char buf[MAX_INPUT_LENGTH];
const char *p;
if( ( p = languageshift( ch, gch, mesg ) ) )
sprintf( buf, "&m$N tell%s the group '$t', in %s.", p,
ch == gch ? "" : "s" );
else
sprintf( buf, "&m$N tell%s the group '$t'.",
ch == gch ? "" : "s" );
act( buf, gch, mesg, ch, TO_CHAR );
}
}
return;
}
/*
* Sent in by Judson Knott <jek@conga.oit.unc.edu>
*/
void do_beep( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *victim;
if( IS_NPC( ch ) )
return;
if( argument[0] == '\0' )
{
send_to_char( "Beep who?\n\r", ch );
return;
}
if( !( victim = get_char_world( ch, argument ) ) )
{
send_to_char( "They are not here.\n\r", ch );
return;
}
if( IS_NPC( victim ) || xIS_SET( victim->act, PLR_NO_BEEP ) )
{
send_to_char( "They are not beepable.\n\r", ch );
act( "$N has just tried to beep you.", victim, NULL, ch, TO_CHAR );
return;
}
charprintf( ch, "&yYou beep %s.&n\n\r", victim->name );
charprintf( victim, "&r\a\a%s has &RBEEP&red you.&n\n\r", ch->name );
return;
}
/*
* It is very important that this be an equivalence relation:
* ( 1 ) A ~ A
* ( 2 ) if A ~ B then B ~ A
* ( 3 ) if A ~ B and B ~ C, then A ~ C
*/
bool is_same_group( CHAR_DATA *ach, CHAR_DATA *bch )
{
if( ach->deleted || bch->deleted )
return FALSE;
if( ach->leader )
ach = ach->leader;
if( bch->leader )
bch = bch->leader;
return ach == bch;
}
bool is_same_clan( CHAR_DATA *ach, CHAR_DATA *bch )
{
if( ach->deleted || bch->deleted )
return FALSE;
if( is_clan( ach ) && is_clan( bch ) )
return ach->pcdata->clan == bch->pcdata->clan;
else
return FALSE;
}
void do_multi_clas( CHAR_DATA *ch, const char *argument )
{
send_to_char( "Why don't you type it in properly?\n\r", ch );
send_to_char( "Just so we're sure you are serious.\n\r", ch );
return;
}
void do_multi_class( CHAR_DATA *ch, const char *argument )
{
int Class;
int i;
bool allowed = TRUE;
int num_classes = 0;
if( IS_NPC( ch ) )
return;
if( get_first_class( ch ) == CLASS_NONE && ch->class > AVAIL_CLASS )
{
send_to_char( "You aren't allowed to multi-class.\n\r", ch );
return;
}
if( argument[0] == '\0' )
{
do_help( ch, "multi-class" );
return;
}
if( !str_cmp( argument, "mage" ) )
Class = CLASS_MAGE;
else if( !str_cmp( argument, "cleric" ) )
Class = CLASS_CLERIC;
else if( !str_cmp( argument, "thief" ) )
Class = CLASS_THIEF;
else if( !str_cmp( argument, "warrior" ) )
Class = CLASS_WARRIOR;
else if( !str_prefix( "martial", argument ) )
Class = CLASS_MARTIAL_ARTIST;
else
{
send_to_char( "There are 5 classes available:\n\r", ch );
send_to_char( "\tMage, Cleric, Thief, Warrior and Martial Artist.\n\r",
ch );
return;
}
if( ch->pcdata->multi_class[Class] >= CLASS_ADEPT )
{
send_to_char( "You allready have that one.\n\r", ch );
return;
}
for( i = 0; i < AVAIL_CLASS; ++i )
{
if( ch->pcdata->multi_class[i] == CLASS_ASPIRING )
{
send_to_char( "One at a time please.\n\r", ch );
return;
}
if( ch->pcdata->multi_class[i] >= CLASS_ADEPT )
num_classes++;
}
if( get_first_class( ch ) != CLASS_NONE
&& get_second_class( ch ) != CLASS_NONE )
num_classes--;
switch( num_classes )
{
case 0:
allowed = TRUE;
break;
case 1:
if( ch->level < 100 || ch->class == Class )
{
allowed = FALSE;
}
break;
case 2:
if( ch->level < 200 || ch->class == Class )
{
allowed = FALSE;
}
break;
case 3:
send_to_char( "You have allready done all you can about this.\n\r", ch );
allowed = FALSE;
break;
default:
send_to_char( "Whoa! that's enough don't you think?\n\r", ch );
allowed = FALSE;
break;
}
if( ch->trust > L_APP )
allowed = TRUE;
if( !allowed )
{
send_to_char( "Sorry you can't multi-class in that class.\n\r", ch );
return;
}
ch->sublevel = 1;
ch->pcdata->multi_class[Class] = CLASS_ASPIRING;
send_to_char( "&gYou have chosen to add the &c", ch );
send_to_char( flag_string( class_flags, &Class ), ch );
send_to_char( "&g class to your character's skills.\n\r", ch );
send_to_char( "Remember the skills from this class "
"will soon become yours.\n\r", ch );
if( num_classes == 0 )
{
send_to_char( "\n\rVery soon you will also have a new class,\n\r",
ch );
send_to_char( "with skills specific to it.\n\r", ch );
}
send_to_char( "&GBest of luck with your initiation.&n\n\r", ch );
return;
}
void do_hire( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *mob;
char arg1[MAX_STRING_LENGTH];
int index;
int cost;
int money;
EVENT *e;
if( IS_NPC( ch ) )
return;
argument = one_argument( argument, arg1 );
if( arg1[0] == '\0' || argument[0] == '\0'
|| !is_number_special( argument ) )
{
send_to_char( "Syntax: hire <who> <bid amount>\n\r", ch );
return;
}
mob = get_char_room( ch, arg1 );
if( !mob )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
if( !IS_NPC( mob ) || !xIS_SET( mob->act, ACT_MERCENARY ) )
{
send_to_char( "They would probably be insulted by your suggestion.\n\r", ch );
return;
}
if( IS_AFFECTED( mob, AFF_MUTE )
|| IS_SET( race_table[mob->race].race_abilities, RACE_MUTE )
|| IS_SET( mob->in_room->room_flags, ROOM_CONE_OF_SILENCE )
|| IS_SET( mob->in_room->room_flags, ROOM_TEMP_CONE_OF_SILENCE ) )
{
act( "$N makes wide gestures with $S hands, it appears that $E's mute.",
ch, NULL, mob, TO_CHAR );
return;
}
if( mob->master || get_time_left( mob->events, evn_mercenary ) >= 0 )
{
send_to_char( "That person is otherwise employed at the moment.\n\r", ch );
return;
}
index = number_fuzzy( ch->level - mob->level );
if( index < -10 )
do_say( mob, "You would humiliate me? I spit on your offer!" );
if( index >= -10 && index < -5 )
do_say( mob, "Hmm, not a very attractive offer, I will wait for better." );
else if( index >= -5 && index < 0 )
do_say( mob, "Ah yes, work. I will take you up on your offer." );
else if( index == 0 )
do_say( mob, "Very well, shall we call it a deal?" );
else if( index > 0 && index <= 5 )
do_say( mob, "Master, your will is mine!" );
else if( index > 5 && index <= 10 )
do_say( mob, "Mighty one, I fear for my safety, I can't accept." );
else
do_say( mob, "Are you stupid!?! What could I offer?" );
if( index < -5 || index > 5 )
{
send_to_char( "Sorry no deal here.\n\r", ch );
return;
}
cost = mob->level * ( 20 - index ) * mob->level / 20;
cost = number_range( cost * 4 / 5, cost * 6 / 5 );
/* extra cost for a hurt mob, mercenaries don't like to die */
if( mob->hit < mob->max_hit * 4 / 5 )
{
act( "$n looks reluctant to take your money.",
mob, NULL, ch, TO_VICT );
cost += mob->max_hit - mob->hit;
}
money = atoi_special( argument );
if( money > ch->gold )
{
do_say( mob, "Hey Tightwad! if you don't have the cash, no deal!" );
return;
}
if( money < 3 * cost )
{
do_say( mob, "Sorry that amount is too small for my liking.\n\r" );
return;
}
if( money > 50 * cost )
do_say( mob, "Master, I am humbled by your riches." );
if( money > ch->gold )
{
do_say( mob, "Hey you dont actually HAVE that money do you?" );
return;
}
ch->gold -= money;
ch->in_room->area->economy += money;
mob->master = ch;
e = create_char_event( mob, evn_mercenary,
UMIN( ( ( money / cost ) - 1 ), 50 ) * PULSE_TICK );
e->data[0] = mob->in_room->vnum;
xSET_BIT( mob->affected_by, AFF_CHARM );
return;
}
void do_setname( CHAR_DATA *ch, const char *argument )
{
char tmp[MAX_INPUT_LENGTH];
char buf[MAX_INPUT_LENGTH];
if( IS_NPC( ch ) )
return;
if( !str_cmp( argument, "clear" )
|| !str_cmp( argument, "reset" )
|| !str_cmp( argument, "none" ) )
{
free_string( ch->short_descr );
ch->short_descr = &str_empty[0];
send_to_char( "Setname cleared.\n\r", ch );
return;
}
else if( argument[0] == '\0' )
{
send_to_char( "Your name is now set to:\n\r", ch );
charprintf( ch, " %s&n.\n\r",
( ch->short_descr && ch->short_descr[0] != '\0' )
? ch->short_descr : ch->name );
return;
}
strcpy( tmp, argument );
str_limit( tmp, 50 );
strcpy( buf, tmp );
kill_colour( tmp, buf );
if( !IS_IMMORTAL( ch ) && !str_str( tmp, ch->name ) )
{
send_to_char( "You need to include your own name in that.\n\r", ch );
return;
}
free_string( ch->short_descr );
ch->short_descr = str_dup( buf );
do_setname( ch, "" );
return;
}
void do_quest( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *mob;
char arg[ MAX_INPUT_LENGTH ];
if( IS_NPC( ch ) )
return;
argument = one_argument( argument, arg );
for( mob = ch->in_room->people; mob; mob = mob->next_in_room )
{
if( xIS_SET( mob->act, ACT_QUESTMASTER ) )
break;
}
if( !str_cmp( arg, "request" ) )
quest_request( ch, mob );
else if( !str_cmp( arg, "complete" ) )
quest_complete( ch, mob );
else if( !str_cmp( arg, "info" ) )
quest_info( ch );
else if( !str_cmp( arg, "identify" ) )
quest_identify( ch, mob, argument );
else if( !str_cmp( arg, "improve" ) )
quest_improve( ch, mob, argument );
else if( !str_cmp( arg, "score" ) || !str_cmp( arg, "points" ) )
{
charprintf( ch, "&gYou have %d quest points.&n\n\r",
ch->pcdata->quest->score );
}
else if( !str_cmp( arg, "time" ) )
{
if( ch->pcdata->quest->time <= 0 )
send_to_char( "You aren't on a quest!\n\r", ch );
else if( ch->pcdata->quest->type == QUEST_NONE )
{
if( ch->pcdata->quest->time == 1 )
send_to_char( "You have less than a minute before you can quest again.\n\r", ch );
else
charprintf( ch, "You have %d minutes left before you can quest again.\n\r",
ch->pcdata->quest->time );
}
else
{
if( ch->pcdata->quest->time == 1 )
send_to_char( "You have less than a minute to complete the quest.\n\r", ch );
else
charprintf( ch, "You have %d minutes left to complete the quest.\n\r",
ch->pcdata->quest->time );
}
}
else if( !str_cmp( arg, "cancel" ) || !str_cmp( arg, "giveup" ) )
{
switch( ch->pcdata->quest->type )
{
case QUEST_NONE:
send_to_char( "But you aren't questing!\n\r", ch );
return;
case QUEST_RACE_CORPSE:
case QUEST_BODY_PART:
free_mem( ch->pcdata->quest->target,
sizeof( struct quest_race_corpse ) );
break;
case QUEST_OBJ_MATERIAL:
free_mem( ch->pcdata->quest->target,
sizeof( struct quest_obj_material ) );
break;
}
ch->pcdata->quest->target = NULL;
ch->pcdata->quest->type = QUEST_NONE;
ch->pcdata->quest->time = 30;
send_to_char( "Ok, giving up on this quest :(\n\r", ch );
}
else
send_to_char(
"Syntax: quest <option> <args>\n\r"
"Options: REQUEST, COMPLETE, INFO, SCORE, TIME, CANCEL, IMPROVE\n\r",
ch );
return;
}
void quest_request( CHAR_DATA *ch, CHAR_DATA *mob )
{
QUEST_DATA *qq = ch->pcdata->quest;
OBJ_INDEX_DATA *pObj;
OBJ_DATA *obj, *in_obj;
ROOM_INDEX_DATA *pRoom = NULL;
MOB_INDEX_DATA *pMob = NULL;
CHAR_DATA *victim = NULL;
int type, period, i;
char buf[ MAX_INPUT_LENGTH ];
if( !mob )
{
send_to_char( "You can't do that here.\n\r", ch );
return;
}
if( qq->time > 0 )
{
send_to_char( "You can't ask for a quest right now.\n\r", ch );
return;
}
type = number_range( 0, QUEST_OBJ_MATERIAL );
period = number_range( 10, 30 );
qq->reward = power( 10000, 5, 20 - period );
qq->reward = number_range( qq->reward * 4 / 5, qq->reward * 6 / 5 );
switch( type )
{
case QUEST_KILL_COMPLETE:
case QUEST_NONE:
default:
qq->time = 5;
qq->type = QUEST_NONE;
sprintf(
buf, "Sorry %s, I don't have any quests for you at the moment.",
ch->name );
do_say( mob, buf );
return;
case QUEST_ITEM:
for( ;; )
{
pObj = get_obj_index( number_range( 100, 65536 ) );
if( pObj && pObj->level <= LEVEL_HERO
&& IS_SET( pObj->extra_flags, ITEM_TAKE ) )
break;
}
for( ;; )
{
pRoom = get_room_index( number_range( 100, 65536 ) );
if( pRoom && ch->level + 2 >= pRoom->area->min
&& ch->level - 2 <= pRoom->area->max
&& !IS_SET( pRoom->area->area_flags, AREA_HIDE ) )
break;
}
sprintf( buf, "Well %s, I would like you to "
"retrieve an item that I lost recently.", ch->name );
do_say( mob, buf );
sprintf( buf, "I lost %s&x somewhere near %s&x.",
pObj->short_descr, pRoom->name );
do_say( mob, buf );
sprintf( buf, "That is a place somewhere in %s&x.", pRoom->area->name );
do_say( mob, buf );
do_say( mob, "Can you get that for me please?" );
obj = create_object( pObj, ch->level );
obj_to_room( obj, pRoom );
set_timer_tick( obj, period * 2 + 5 );
create_obj_event( obj, evn_imp_grab,
( period * 2 + 6 ) * PULSE_TICK );
SET_BIT( obj->extra_flags, ITEM_QUEST|ITEM_TAKE );
qq->target = (void *)obj;
break;
case QUEST_KILL:
for( i = 0; i < 10000; i++ )
{
pRoom = NULL;
pMob = get_mob_index( number_range( 100, 65536 ) );
if( pMob && pMob->level >= ch->level - 1
&& pMob->level < ch->level + UMIN( 10, ch->level / 3 )
&& pMob->count > 0
&& get_trust( ch ) + 2 >= pMob->area->min
&& !IS_SET( pMob->area->area_flags, AREA_HIDE ) )
for( victim = char_list; victim; victim = victim->next )
{
if( IS_NPC( victim ) && victim->pIndexData == pMob
&& !IS_SET( victim->in_room->room_flags, ROOM_SAFE ) )
{
pRoom = victim->in_room;
break;
}
}
if( pRoom )
break;
}
if( !victim )
{
send_to_char( "Bummer, no mobs your level.\n\r", ch );
qq->time = 5;
qq->type = QUEST_NONE;
return;
}
sprintf( buf, "%s my friend, I have a grim task for you.", ch->name );
do_say( mob, buf );
sprintf( buf, "My dire enemy, %s&x, has thwarted me for too long.",
pMob->short_descr );
do_say( mob, buf );
sprintf( buf, "Seem them out near %s&x and kill them for me if you please.",
pRoom->name );
do_say( mob, buf );
sprintf( buf, "That is a place somewhere in %s.", pRoom->area->name );
do_say( mob, buf );
qq->target = (void *)pMob;
qq->reward = power( qq->reward, 5, victim->level - ch->level );
break;
case QUEST_BODY_PART:
for( i = 0; part_loss_table[i].chance > 0; ++i )
;
i = number_range( 0, i - 1 );
qq->reward *= 8;
qq->reward /= part_loss_table[i].chance
- ( (i == 0) ? 0 : part_loss_table[i-1].chance );
qq->target = alloc_mem( sizeof( struct quest_race_corpse ) );
((struct quest_race_corpse *)qq->target)->race
= part_loss_table[i].body_parts;
((struct quest_race_corpse *)qq->target)->min_lvl
= ch->level - 3 + dice( 2, 5 );
sprintf( buf, "%s, my studies require me to study particular limbs.",
ch->name );
do_say( mob, buf );
i = part_loss_table[i].body_parts;
sprintf( buf, "Please would you find me a limb that has: %s.",
flag_string( body_part_flags, &i ) );
do_say( mob, buf );
sprintf( buf, "Could you make the limb at least level %d?",
((struct quest_race_corpse *)qq->target)->min_lvl );
do_say( mob, buf );
break;
case QUEST_RACE_CORPSE:
for( i = 0; i < 10000; i++ )
{
pMob = get_mob_index( number_range( 100, 65536 ) );
if( pMob && pMob->level >= ch->level - 1
&& pMob->level < ch->level + UMIN( 10, ch->level / 3 )
&& pMob->count > 0
&& get_trust( ch ) + 2 >= pMob->area->min
&& !IS_SET( pMob->area->area_flags, AREA_HIDE ) )
break;
}
if( !pMob )
{
send_to_char( "Bummer, no mobs your level.\n\r", ch );
qq->time = 5;
qq->type = QUEST_NONE;
return;
}
i = pMob->race;
sprintf( buf, "%s, can you please find me a %s corpse?",
ch->name, race_table[i].name );
do_say( mob, buf );
do_say( mob, "I find that my books do not give me sufficient information on these." );
do_say( mob, "I would like to do a post mortem examination of one." );
qq->target = alloc_mem( sizeof( struct quest_race_corpse ) );
((struct quest_race_corpse *)qq->target)->race = i;
((struct quest_race_corpse *)qq->target)->min_lvl
= pMob->level;
sprintf( buf, "Please make the corpse of at least level %d.",
((struct quest_race_corpse *)qq->target)->min_lvl );
do_say( mob, buf );
qq->reward = qq->reward / 3 + qq->reward * race_tnl( i ) / 2000;
break;
case QUEST_OBJ_MATERIAL:
do
{
for( i = 0; material_flags[i].name[0]; i++ )
;
i = number_range( 0, i - 1 );
for( obj = object_list; obj; obj = obj->next )
if( !obj->deleted
&& obj->pIndexData->material == material_flags[i].bit
&& obj->level < ch->level - 10 )
break;
}
while( !obj );
qq->reward = qq->reward * 200
- 3 * qq->reward * UMIN( 100, material_flags[i].bit ) / 2;
qq->reward /= 100;
qq->target = alloc_mem( sizeof( struct quest_obj_material ) );
((struct quest_obj_material *)qq->target)->material
= material_flags[i].bit;
sprintf( buf, "%s, I have need of a quantity of %s.",
ch->name, material_flags[i].name );
do_say( mob, buf );
i = dice( 3, 6 );
qq->reward *= i + 8;
qq->reward /= 15;
((struct quest_obj_material *)qq->target)->min_weight = i;
sprintf( buf, "I need you to fetch more than %dKg of this material.",
i );
do_say( mob, buf );
for( in_obj = obj; in_obj->in_obj; in_obj = in_obj->in_obj )
;
if( in_obj->carried_by )
{
sprintf( buf, "To start, you can find some carried by %s&x.\n\r",
PERS( in_obj->carried_by, ch ) );
}
else
{
sprintf( buf, "For starters, you can find some in %s&x.\n\r",
!in_obj->in_room ? "somewhere" : in_obj->in_room->name );
}
do_say( mob, buf );
do_say( mob,
"Then I would be able to construct a device I'm working on." );
break;
}
do_say( mob, "I would be most grateful if you would do this for me." );
sprintf( buf, "I'll give you %d minutes to complete this quest.",
period );
do_say( mob, buf );
qq->time = period;
qq->type = type;
return;
}
void quest_complete( CHAR_DATA *ch, CHAR_DATA *mob )
{
QUEST_DATA *qq = ch->pcdata->quest;
OBJ_DATA *obj, *objnext;
int pts;
char buf[ MAX_INPUT_LENGTH ];
if( !mob )
{
send_to_char( "You can't do that here.\n\r", ch );
return;
}
switch( qq->type )
{
case QUEST_NONE:
default:
send_to_char( "You aren't questing at the moment.\n\r", ch );
return;
case QUEST_ITEM:
for( obj = ch->carrying; obj; obj = obj->next_content )
if( !obj->deleted && obj == (OBJ_DATA *)qq->target )
break;
if( !obj )
{
do_say( mob, "But you haven't completed the quest!" );
return;
}
obj_from_char( obj );
extract_obj( obj );
break;
case QUEST_KILL:
do_say( mob, "But you haven't completed the quest!" );
return;
case QUEST_KILL_COMPLETE:
break;
case QUEST_BODY_PART:
for( obj = ch->carrying; obj; obj = obj->next_content )
if( !obj->deleted && obj->item_type == ITEM_LIMB
&& obj->level >= ((struct quest_race_corpse *)qq->target)->min_lvl
&& ( ( obj->value[0]
& ((struct quest_race_corpse *)qq->target)->race )
== ((struct quest_race_corpse *)qq->target)->race ) )
break;
if( !obj )
{
do_say( mob, "But you haven't completed the quest!" );
return;
}
obj_from_char( obj );
extract_obj( obj );
break;
case QUEST_RACE_CORPSE:
for( obj = ch->carrying; obj; obj = obj->next_content )
if( !obj->deleted && obj->item_type == ITEM_CORPSE_NPC
&& obj->level >= ((struct quest_race_corpse *)qq->target)->min_lvl
&& obj->value[0] == ((struct quest_race_corpse *)qq->target)->race )
break;
if( !obj )
{
do_say( mob, "But you haven't completed the quest!" );
return;
}
free_mem( qq->target, sizeof( struct quest_race_corpse ) );
obj_from_char( obj );
extract_obj( obj );
break;
case QUEST_OBJ_MATERIAL:
pts = 0;
for( obj = ch->carrying; obj; obj = obj->next_content )
if( !obj->deleted && obj->wear_loc == WEAR_NONE
&& obj->pIndexData->material == ((struct quest_obj_material *)qq->target)->material )
{
SET_BIT( obj->extra_flags, ITEM_QUEST );
if( ( pts += obj->weight ) >= ((struct quest_obj_material *)qq->target)->min_weight )
break;
}
if( pts < ((struct quest_obj_material *)qq->target)->min_weight )
pts = 0;
for( obj = ch->carrying; obj; obj = objnext )
{
objnext = obj->next_content;
if( IS_SET( obj->extra_flags, ITEM_QUEST ) )
{
if( pts > 0 )
{
obj_from_char( obj );
extract_obj( obj );
}
else
REMOVE_BIT( obj->extra_flags, ITEM_QUEST );
}
}
if( pts == 0 )
{
do_say( mob, "But you haven't completed the quest!" );
return;
}
free_mem( qq->target, sizeof( struct quest_obj_material ) );
break;
}
sprintf( buf, "Thank you very much %s.", ch->name );
do_say( mob, buf );
pts = (qq->reward / 1000) - 5 + dice( 2, 5 );
sprintf( buf, "For that I'll give you %d quest points and %d gold.",
pts, qq->reward );
do_say( mob, buf );
ch->gold += qq->reward;
qq->score += pts;
qq->time = 30;
qq->reward = 0;
qq->type = QUEST_NONE;
qq->target = NULL;
return;
}
void quest_info( CHAR_DATA *ch )
{
QUEST_DATA *qq = ch->pcdata->quest;
switch( qq->type )
{
case QUEST_NONE:
default:
send_to_char( "You aren't questing at the moment.\n\r", ch );
break;
case QUEST_ITEM:
act( "&gYou are sent to get $p.", ch, qq->target, NULL, TO_CHAR );
break;
case QUEST_KILL_COMPLETE:
case QUEST_KILL:
act( "&gYou are sent to kill $t.", ch,
((MOB_INDEX_DATA *)qq->target)->short_descr, NULL, TO_CHAR );
break;
case QUEST_BODY_PART:
charprintf( ch, "&gYou are sent to find a limb of at least level %d.&n\n\r",
((struct quest_race_corpse *)qq->target)->min_lvl );
charprintf( ch, "&gIt must contain the limbs: %s.&n\n\r",
flag_string( body_part_flags, &((struct quest_race_corpse *)qq->target)->race ) );
break;
case QUEST_RACE_CORPSE:
charprintf( ch, "&gYou are sent to find a %s corpse of at least level %d.&n\n\r",
race_table[((struct quest_race_corpse *)qq->target)->race].name,
((struct quest_race_corpse *)qq->target)->min_lvl );
break;
case QUEST_OBJ_MATERIAL:
charprintf( ch, "&gYou are sent to get %dKg of %s.&n\n\r",
((struct quest_obj_material *)qq->target)->min_weight,
flag_string( material_flags, &((struct quest_obj_material *)qq->target)->material ) );
break;
}
return;
}
void quest_identify( CHAR_DATA *ch, CHAR_DATA *mob, const char *argument )
{
OBJ_DATA *obj;
char buf[MAX_INPUT_LENGTH];
if( !( obj = get_obj_carry( mob, argument ) ) )
{
do_say( mob, "I don't carry that item." );
return;
}
sprintf( buf, "The %s item has these properties:", obj->short_descr );
do_say( mob, buf );
spell_identify( skill_lookup( "identify" ), mob->level, ch, obj );
return;
}
void quest_improve( CHAR_DATA *ch, CHAR_DATA *mob, const char *argument )
{
OBJ_DATA *obj;
AFFECT_DATA *paf;
char target[MAX_INPUT_LENGTH];
char loc[MAX_INPUT_LENGTH];
int type, sn;
int cost;
int max;
bool found = FALSE;
if( IS_NPC( ch ) )
return;
argument = one_argument( argument, target );
argument = one_argument( argument, loc );
if( !( obj = get_obj_carry( ch, target ) ) )
{
send_to_char( "Usage: quest improve <object> <type>\n\r", ch );
return;
}
if( obj->wear_loc != WEAR_NONE )
{
send_to_char( "Take it off first.\n\r", ch );
return;
}
if( !str_cmp( loc, "ac" ) )
{
type = APPLY_AC; cost = 10; max = obj->level / -2;
}
else if( !str_cmp( loc, "attackroll" ) || !str_cmp( loc, "hitroll" ) )
{
type = APPLY_HITROLL; cost = 25; max = obj->level / 10;
}
else if( !str_cmp( loc, "damroll" ) )
{
type = APPLY_DAMROLL; cost = 20; max = obj->level / 10;
}
else if( !str_cmp( loc, "str" ) || !str_cmp( loc, "strength" ) )
{
type = APPLY_STR; cost = 50; max = 2;
}
else if( !str_cmp( loc, "int" ) || !str_cmp( loc, "intelligence" ) )
{
type = APPLY_INT; cost = 50; max = 2;
}
else if( !str_cmp( loc, "wis" ) || !str_cmp( loc, "wisdom" ) )
{
type = APPLY_WIS; cost = 50; max = 2;
}
else if( !str_cmp( loc, "dex" ) || !str_cmp( loc, "dexterity" ) )
{
type = APPLY_DEX; cost = 50; max = 2;
}
else if( !str_cmp( loc, "con" ) || !str_cmp( loc, "constitution" ) )
{
type = APPLY_CON; cost = 50; max = 2;
}
else if( !str_cmp( loc, "resilience" ) )
{
type = APPLY_RESILIENCE; cost = 100; max = -10;
}
else
{
send_to_char( "Locations are: ac, attackroll, damroll, str, int, wis, "
"dex, con, resilience.\n\r", ch );
send_to_char( "Use: 'quest improve <obj> <loc> appraise' for costs.\n\r", ch );
return;
}
sn = skill_lookup( "quest improvement" );
for( paf = obj->affected; paf; paf = paf->next )
{
int mod;
if( paf->location == APPLY_AC || type == APPLY_RESILIENCE )
mod = -1 * paf->modifier;
else
mod = paf->modifier;
if( paf->type == sn )
{
if( paf->location == type )
cost = power( cost, 100, mod );
else
cost = power( cost, 10, mod );
}
}
if( argument[0] != '\0' )
{
charprintf( ch, "Cost to %s %s by 1 point: %d qp.\n\r",
( type == APPLY_AC || type == APPLY_RESILIENCE )
? "decrease" : "increase",
flag_string( apply_flags, &type ), cost );
return;
}
if( ch->pcdata->quest->score < cost )
{
send_to_char( "You can't afford that improvement.\n\r", ch );
return;
}
for( paf = obj->affected; paf; paf = paf->next )
{
if( paf->deleted || paf->type != sn
|| paf->location != type )
continue;
if( type == APPLY_AC || type == APPLY_RESILIENCE )
{
if( paf->modifier <= max )
{
send_to_char( "That item cannot be improved further.\n\r", ch );
return;
}
paf->modifier--;
}
else
{
if( paf->modifier >= max )
{
send_to_char( "That item cannot be improved further.\n\r", ch );
return;
}
paf->modifier++;
}
found = TRUE;
break;
}
if( !found )
{
paf = new_affect( );
paf->type = sn;
paf->duration = -1;
paf->location = type;
if( type == APPLY_AC || type == APPLY_RESILIENCE )
paf->modifier = -1;
else
paf->modifier = 1;
vzero( paf->bitvector );
paf->next = obj->affected;
obj->affected = paf;
}
ch->pcdata->quest->score -= cost;
charprintf( ch, "&gYou paid &y%d&g qp to improve &y%s&g.&n\n\r", cost,
flag_string( apply_flags, &type ) );
return;
}
void do_speak( CHAR_DATA *ch, const char *argument )
{
int lang, sn;
if( IS_NPC( ch ) )
return;
if( !*argument )
{
int pos = 10;
char buf[32];
send_to_char( "&gYour race can speak the following languages:\n\r"
" &yCommon", ch );
for( lang = 0; *language_flags[lang].name; ++lang )
{
sprintf( buf, "%s language", language_flags[lang].name );
sn = skill_lookup( buf );
if( IS_SET( race_table[ch->race].languages,
language_flags[lang].bit )
|| ( sn >= 0 && ch->pcdata->learned[sn] ) )
{
pos += strlen( language_flags[lang].name ) + 1;
if( pos > 75 )
{
send_to_char( "&n\n\r &y", ch );
pos = 3;
}
charprintf( ch, " %s", language_flags[lang].name );
}
}
send_to_char( "&n\n\r", ch );
return;
}
if( flag_value( &lang, language_flags, argument ) == NO_FLAG )
{
send_to_char( "That isn't a language.\n\r", ch );
return;
}
if( ch->level < LEVEL_HERO && lang != LANG_COMMON
&& !can_speak( ch, lang ) )
{
send_to_char( "You can't speak that yet.\n\r", ch );
return;
}
ch->pcdata->language = lang;
send_to_char( "You will now speak ", ch );
send_to_char( flag_string( language_flags, &lang ), ch );
send_to_char( ".\n\r", ch );
return;
}
void wiznetf( CHAR_DATA *ch, int chan, int level, const char *fmt, ... )
{
char buf[MAX_STRING_LENGTH];
va_list args;
va_start( args, fmt );
vsprintf( buf, fmt, args );
va_end( args );
wiznet( ch, chan, level, buf );
}
void wiznet( CHAR_DATA *ch, int chan, int level, const char *string )
{
DESCRIPTOR_DATA *d;
char buf[ MAX_STRING_LENGTH ];
strcpy( buf, "&c&4[WIZNET]&n" );
switch( chan )
{
default:
strcat( buf, "&c " );
break;
case WIZ_LOGINS:
strcat( buf, "&b[LOGIN]&c " );
break;
case WIZ_TICKS:
strcat( buf, "&y[TICK]&c " );
break;
case WIZ_DEATHS:
strcat( buf, "&y[DEATH]&c " );
break;
case WIZ_LEVELS:
strcat( buf, "&b[LEVEL]&c " );
break;
case WIZ_COMMANDS:
strcat( buf, "&m[COMMAND] " );
break;
case WIZ_MISC:
strcat( buf, "&w[MISC] " );
break;
case WIZ_CREATE:
strcat( buf, "&g[CREATE] " );
break;
case WIZ_CLAN:
strcat( buf, "&r{CLAN} " );
break;
case WIZ_DEBUG:
strcat( buf, "&r<<&R!&r>> " );
break;
}
strcat( buf, string );
strcat( buf, "&n\n\r" );
for ( d = descriptor_list; d; d = d->next )
{
if( !IS_SET( d->interpreter->flags, INTERPRETER_NOMESSAGE )
&& IS_IMMORTAL( d->character )
&& get_trust( d->character ) >= level
&& IS_SET( CH( d )->deaf, chan )
&& IS_SET( CH( d )->deaf, WIZ_ON )
&& d->character != ch
&& ( ch ? can_see( d->character, ch ) : TRUE ) )
send_to_char( buf, d->character );
}
return;
}
/* Healer code written for Merc 2.0 muds by Alander
direct questions or comments to rtaylor@cie-2.uoregon.edu
any use of this code must include this header */
/* I changed it, can I have my own header? please? --Sym :P */
void do_heal( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *mob;
int cost,sn;
SPELL_FUN *spell;
const char *words;
/* check for healer */
for( mob = ch->in_room->people; mob; mob = mob->next_in_room )
{
if( IS_NPC( mob ) && xIS_SET( mob->act, ACT_HEALER ) )
break;
}
if( mob == NULL )
{
send_to_char( "You can't do that here.\n\r", ch );
return;
}
if( mob->fighting != NULL )
{
act( "&c$N exclaims 'Can't you see i'm busy !!!'",
ch, NULL, mob, TO_CHAR);
return;
}
if( mob->level < ch->level - 10 )
{
act( "&c$N says 'I can't help you, sorry'", ch, NULL, mob, TO_CHAR );
return;
}
if( argument[0] == '\0' )
{
/* display price list */
act( "&c$N says 'I offer the following spells:'",
ch, NULL, mob, TO_CHAR );
charprintf(
ch, " &ccure&g: cure wounds &y%14d&g gold&n\n\r",
125 * mob->level );
charprintf( ch, " &cheal&g: healing spell &y%12d&g gold&n\n\r",
250 * mob->level );
send_to_char(
" &cblind&g: cure blindness &y2000&g gold&n\n\r", ch );
charprintf( ch, " &cdisease&g: cure disease &y%13d&g gold&n\n\r",
100 * mob->level );
send_to_char(
" &cpoison&g: cure poison &y2500&g gold&n\n\r", ch );
charprintf( ch, " &cuncurse&g: remove hex &y%13d&g gold&n\n\r",
250 * mob->level );
charprintf( ch, " &cendurance&g: restore movement &y%9d&g gold&n\n\r",
12 * mob->level );
charprintf( ch, " &cmana&g: mana balm &y%16d&g gold&n\n\r",
500 * mob->level );
send_to_char(
" &cfeast&g: complete nourishment &y10000&g gold&n\n\r", ch );
send_to_char( "&gType heal <type> to be healed.&n\n\r", ch );
return;
}
switch( argument[0] )
{
case 'c' :
spell = spell_cure;
sn = skill_lookup( "cure" );
words = "judicandus";
cost = 150 * mob->level;
break;
case 'h' :
spell = spell_heal;
sn = skill_lookup( "heal" );
words = "pzar";
cost = 500 * mob->level;
break;
case 'b' :
spell = spell_cure_blindness;
sn = skill_lookup( "cure blindness" );
words = "judicandus noselacri";
cost = 2000;
break;
case 'd' :
spell = spell_lay_hands;
sn = skill_lookup( "lay hands" );
words = "judicandus eugzagz";
cost = 100 * mob->level;
break;
case 'p' :
spell = spell_cure_poison;
sn = skill_lookup("cure poison");
words = "judicandus sausabru";
cost = 2500;
break;
case 'u' :
spell = spell_remove_hex;
sn = skill_lookup( "remove hex" );
words = "candussido judifgz";
cost = 250 * mob->level;
break;
case 'e' :
spell = spell_endurance;
sn = skill_lookup( "endurance" );
words = "candusima";
cost = 12 * mob->level;
break;
case 'm' :
spell = spell_mana_balm;
sn = skill_lookup( "mana balm" );
words = "waia barw";
cost = 1000 * mob->level;
break;
case 'f':
spell = spell_feast;
sn = skill_lookup( "feast" );
words = "yjumagh";
cost = 10000;
break;
default :
act( "&c$N says 'Type 'heal' for a list of spells.'",
ch, NULL, mob, TO_CHAR );
return;
}
if( cost > ch->gold )
{
act( "&c$N says 'You do not have enough gold for my services.'",
ch, NULL, mob, TO_CHAR );
return;
}
WAIT_STATE( ch, PULSE_VIOLENCE );
ch->gold -= cost;
act( "$n utters the words '$T'.", mob, NULL, words, TO_ROOM );
if( sn == -1 )
return;
spell( sn, mob->level, mob, ch );
}
void do_bounty( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *victim;
char arg[MAX_INPUT_LENGTH];
int gold;
if( IS_NPC( ch ) )
return;
argument = one_argument( argument, arg );
if( arg[0] == '\0' )
{
send_to_char( "Usage: bounty <char> [addgold]\n\r", ch );
return;
}
victim = get_char_world( ch, arg );
if( !victim )
{
send_to_char( "You can't find that person.\n\r", ch );
return;
}
if( argument[0] == '\0' || !is_number_special( argument ) )
{
if( !IS_NPC( victim ) && victim->pcdata->bounty > 0 )
charprintf( ch, "%s has a bounty of %s gold on their head.\n\r",
victim->name,
int_to_str_special( victim->pcdata->bounty ) );
else
send_to_char( "Usage: bounty <char> [addgold]\n\r", ch );
return;
}
if( IS_NPC( victim ) || ( !is_clan_enemy( victim, ch )
&& !IS_IMMORTAL( ch ) ) )
{
send_to_char( "That person is no enemy of yours.\n\r", ch );
return;
}
gold = atoi_special( argument );
/* Minimum bounty, to stop piddly amounts being put up */
if( gold < UMIN( 500000, ch->level * ch->level * 5 ) )
{
charprintf( ch, "Please put up a price of at least %s gold!\n\r",
int_to_str_special( UMIN( 500000,
ch->level * ch->level * 5 ) ) );
return;
}
if( ch->gold + ch->pcdata->banked < gold )
{
send_to_char( "You have insufficient funds at your disposal.\n\r", ch );
return;
}
ch->gold -= gold;
if( ch->gold < 0 )
{
ch->pcdata->banked += ch->gold;
ch->gold = 0;
}
victim->pcdata->bounty += gold;
sprintf( arg, "%s has put a price of %s gold on the head of %s!!!",
ch->name, int_to_str_special( gold ), victim->name );
talk_channel( NULL, arg, CHANNEL_INFO, "INFO" );
}
void do_become( CHAR_DATA *ch, const char *argument )
{
DESCRIPTOR_DATA *d;
if( IS_NPC( ch ) || !ch->desc )
{
send_to_char( "You can't do that!\n\r", ch );
return;
}
if( ch->level < 2 )
{
send_to_char( "You aren't high enough level.\n\r", ch );
return;
}
if( !strcmp( ch->name, argument ) )
{
charprintf( ch, "Tada, you suddenly turn into %s!\n\r", ch->name );
return;
}
if( !can_quit( ch ) )
return;
charprintf( ch, "You slowly transform into %s!\n\r", argument );
d = quit_char( ch );
if( d )
{
d->interpreter = get_interpreter( "getName" );
nanny_get_name( d, argument );
}
}
#define IS_TRADE_LOCKED( _ch ) \
( IS_SET( (_ch)->pcdata->trade->flags, TRADE_LOCKED ) \
|| IS_SET( (_ch)->pcdata->trade->other->flags, TRADE_LOCKED ) )
/*
* Allocate and initialise a trade object for a character.
*/
TRADE_DATA *new_trade( CHAR_DATA *ch )
{
TRADE_DATA *tr;
int i;
tr = (TRADE_DATA *)alloc_mem( sizeof( TRADE_DATA ) );
tr->ch = ch;
tr->flags = 0;
tr->gold = 0;
for( i = 0; i < MAX_TRADE_OBJ; ++i )
tr->objs[i] = NULL;
return tr;
}
/*
* Display an offer of trade from victim to ch.
*/
void show_trade( CHAR_DATA *ch, CHAR_DATA *victim )
{
OBJ_DATA *obj;
char buf[MAX_INPUT_LENGTH];
int i;
const char *kw;
sprintf( buf, "&yGold: %d coins.&n\n\r", victim->pcdata->trade->gold );
send_to_char( buf, ch );
for( i = 0; i < MAX_TRADE_OBJ; ++i )
{
obj = victim->pcdata->trade->objs[i];
if( !obj )
continue;
sprintf( buf, "&gObject: %s&n\n\r", obj->short_descr );
send_to_char( buf, ch );
}
if( ch == victim )
kw = "have";
else
kw = "has";
if( IS_SET( victim->pcdata->trade->flags, TRADE_AGREED ) )
act( "&G$N $t agreed to the trade.", ch, kw, victim, TO_CHAR );
else if( IS_SET( victim->pcdata->trade->flags, TRADE_LOCKED ) )
act( "&G$N $t set a lock on the trade.", ch, kw, victim, TO_CHAR );
return;
}
/*
* Finds a trade object.
*/
OBJ_DATA *find_trade_obj( CHAR_DATA *ch, CHAR_DATA *victim, const char *name )
{
OBJ_DATA *obj;
int i;
for( i = 0; i < MAX_TRADE_OBJ; ++i )
{
obj = victim->pcdata->trade->objs[i];
if( obj && is_name( name, obj->name ) )
return obj;
}
return NULL;
}
/*
* Checks that the items offered in trade still exist.
*/
bool check_trade( CHAR_DATA *ch, CHAR_DATA *victim )
{
OBJ_DATA *obj;
int i, nitem = 0, witem = 0;
for( i = 0; i < MAX_TRADE_OBJ; ++i )
{
obj = ch->pcdata->trade->objs[i];
if( !obj )
continue;
if( obj->carried_by != ch )
{
send_to_char( "An item is missing, the trade must be cancelled.\n\r", ch );
send_to_char( "An item is missing, the trade must be cancelled.\n\r", victim );
return FALSE;
}
if( obj->contains )
{
send_to_char( "Containers must be empty for a trade, forcing withdrawal.\n\r", ch );
send_to_char( "Containers must be empty for a trade, forcing withdrawal.\n\r", victim );
return FALSE;
}
nitem++;
witem += get_obj_weight( obj );
}
if( victim->carry_number + nitem > can_carry_n( victim )
|| victim->carry_weight + witem > can_carry_w( victim ) )
{
send_to_char( "You can't carry the items!\n\r", ch );
return FALSE;
}
return TRUE;
}
/*
* Move items in trade from victim to ch.
*/
void affect_trade( CHAR_DATA *ch, CHAR_DATA *victim )
{
OBJ_DATA *obj;
int i;
for( i = 0; i < MAX_TRADE_OBJ; ++i )
{
obj = victim->pcdata->trade->objs[i];
if( !obj )
continue;
act( "&g$n give$% $p to $N.", victim, obj, ch, TO_ALL );
obj_from_char( obj );
obj_to_char( obj, ch );
}
if( victim->pcdata->trade->gold > 0 )
act( "&g$n give$% some gold to $N.", victim, NULL, ch, TO_ALL );
ch->gold += victim->pcdata->trade->gold;
return;
}
/*
* Symposium's secure trade interface.
*/
void do_trade( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *victim;
OBJ_DATA *obj;
char arg[MAX_INPUT_LENGTH];
int i;
if( IS_NPC( ch ) )
return;
argument = one_argument( argument, arg );
if( !ch->pcdata->trade )
{
if( total_mana( ch->mana ) < 100 + ch->level * 2 )
{
send_to_char( "You need some more mana in order to initiate a trade.\n\r", ch );
return;
}
if( !str_cmp( arg, "offer" ) )
{
take_generic_mana( ch, 100 + ch->level * 2 );
ch->pcdata->trade = new_trade( ch );
if( argument[0] != '\0'
&& ( victim = get_char_room( ch, argument ) )
&& victim != ch && !IS_NPC( victim ) )
{
ch->pcdata->trade->other = new_trade( victim );
ch->pcdata->trade->other->other = ch->pcdata->trade;
act( "&c$n open$% an offer for a trade session with $N.",
ch, NULL, victim, TO_ALL );
}
else
{
ch->pcdata->trade->other = NULL;
act( "&c$n open$% an offer for a trade session.",
ch, NULL, NULL, TO_ALL );
}
return;
}
if( !str_cmp( arg, "join" ) )
{
if( argument[0] == '\0'
|| !( victim = get_char_room( ch, argument ) )
|| IS_NPC( victim ) )
{
send_to_char( "That person is not here.\n\r", ch );
return;
}
if( victim->pcdata->trade == NULL )
{
send_to_char( "They have not offered to trade.\n\r", ch );
return;
}
if( victim->pcdata->trade->other != NULL
&& victim->pcdata->trade->other->ch != ch )
{
act( "&r$N has restricted the trade so you can't join.",
ch, NULL, victim, TO_CHAR );
return;
}
take_generic_mana( ch, 100 + ch->level * 2 );
if( !victim->pcdata->trade->other )
{
victim->pcdata->trade->other = new_trade( ch );
victim->pcdata->trade->other->other = victim->pcdata->trade;
}
ch->pcdata->trade = victim->pcdata->trade->other;
ch->pcdata->trade->ch = ch; /* sanity check */
act( "&c$n join$% a trade session with $N.",
ch, NULL, victim, TO_ALL );
return;
}
send_to_char( "Type HELP TRADE to get more information on trading securely.\n\r", ch );
return;
}
if( !str_cmp( arg, "withdraw" ) || !str_cmp( arg, "leave" ) )
{
send_to_char( "&cYou withdraw from the trade.&n\n\r", ch );
if( ch->pcdata->trade->other )
{
victim = ch->pcdata->trade->other->ch;
if( victim->pcdata->trade )
{
act( "&c$n withdraws from the trade.",
ch, NULL, victim, TO_VICT );
victim->gold += victim->pcdata->trade->gold;
victim->pcdata->trade = NULL;
}
free_mem( ch->pcdata->trade->other, sizeof( TRADE_DATA ) );
}
ch->gold += ch->pcdata->trade->gold;
/* Note here that "victim" may not have a pointer to their trade
* object if they haven't accepted the deal. */
free_mem( ch->pcdata->trade, sizeof( TRADE_DATA ) );
ch->pcdata->trade = NULL;
return;
}
if( !ch->pcdata->trade->other )
{
send_to_char( "No-one has accepted the offer of trade yet.\n\r", ch );
return;
}
/* From here down a trade exists */
victim = ch->pcdata->trade->other->ch;
if( !str_prefix( arg, "examine" ) )
{
CHAR_DATA *tmpch;
if( argument[0] == '\0' )
{
send_to_char( "&mYour offer is as follows:\n\r", ch );
show_trade( ch, ch );
act( "&m$N's offer is as follows:", ch, NULL, victim, TO_CHAR );
show_trade( ch, victim );
return;
}
if( !( obj = find_trade_obj( ch, victim, argument ) )
&& !( obj = find_trade_obj( ch, ch, argument ) ) )
{
send_to_char( "You can't find that object.\n\r", ch );
return;
}
tmpch = obj->carried_by;
if( tmpch != ch && tmpch != victim )
{
send_to_char( "Object moved, ending trade.\n\r", ch );
send_to_char( "An object moved, forcing an end to the trade.\n\r",
victim );
do_trade( ch, "withdraw" );
return;
}
if( tmpch != ch )
{
obj_from_char( obj );
obj_to_char( obj, ch );
}
send_to_char( "&gYou examine the object to determine its worth...&n\n\r", ch );
do_examine( ch, obj->name );
if( tmpch != ch )
{
obj_from_char( obj );
obj_to_char( obj, tmpch );
}
return;
}
if( !str_prefix( arg, "identify" ) )
{
if( argument[0] == '\0' )
{
send_to_char( "Which item did you want to identify?\n\r", ch );
return;
}
if( !( obj = find_trade_obj( ch, victim, argument ) )
&& !( obj = find_trade_obj( ch, ch, argument ) ) )
{
send_to_char( "You can't find that object.\n\r", ch );
return;
}
if( ch->gold < 50 + ch->level * 2 )
{
send_to_char( "You have insufficient funds for identify.\n\r",
ch );
return;
}
ch->gold -= 50 + ch->level * 2;
send_to_char( "&gYou examine the object to determine its worth...&n\n\r", ch );
spell_identify( skill_lookup( "identify" ), ch->level, ch, obj );
return;
}
if( !str_prefix( arg, "add" ) )
{
if( IS_TRADE_LOCKED( ch ) )
{
send_to_char( "&rYou cannot make a change to a locked trade.&n\n\r", ch );
return;
}
if( is_number( argument ) )
{
i = atoi( argument );
if( i <= 0 || i > ch->gold )
{
send_to_char( "You have insufficient funds for that.\n\r", ch );
return;
}
ch->pcdata->trade->gold += i;
ch->gold -= i;
sprintf( arg, "&yYou add %d gold to your trade.&n\n\r", i );
send_to_char( arg, ch );
sprintf( arg, "&y$n adds %d to $s trade.", i );
act( arg, ch, NULL, victim, TO_VICT );
return;
}
if( !( obj = get_obj_carry( ch, argument ) ) )
{
send_to_char( "You can't find that item.\n\r", ch );
return;
}
if( !can_drop_obj( ch, obj ) || obj->contains )
{
send_to_char( "You cannot offer that item.\n\r", ch );
return;
}
for( i = 0; i < MAX_TRADE_OBJ; ++i )
{
if( ch->pcdata->trade->objs[i] == NULL )
{
ch->pcdata->trade->objs[i] = obj;
act( "&gYou add $p to the trade.", ch, obj, victim, TO_CHAR );
act( "&g$n adds $p to the trade.", ch, obj, victim, TO_VICT );
return;
}
}
send_to_char( "You have used all of your slots for items, sorry.\n\r", ch );
return;
}
if( !str_prefix( arg, "remove" ) )
{
if( IS_TRADE_LOCKED( ch ) )
{
send_to_char( "&rYou cannot make a change to a locked trade.&n\n\r", ch );
return;
}
if( is_number( argument ) )
{
i = atoi( argument );
if( i <= 0 || i > ch->pcdata->trade->gold )
{
send_to_char( "You cannot remove that amount!\n\r", ch );
return;
}
ch->pcdata->trade->gold -= i;
ch->gold += i;
sprintf( arg, "&yYou remove %d gold from your trade.&n\n\r", i );
send_to_char( arg, ch );
sprintf( arg, "&y$n removes %d from $s trade.", i );
act( arg, ch, NULL, victim, TO_VICT );
return;
}
if( !( obj = find_trade_obj( ch, ch, argument ) ) )
{
send_to_char( "You can't find that item.\n\r", ch );
return;
}
for( i = 0; i < MAX_TRADE_OBJ; ++i )
{
if( obj == ch->pcdata->trade->objs[i] )
ch->pcdata->trade->objs[i] = NULL;
}
act( "&gYou remove $p from the trade.", ch, obj, victim, TO_CHAR );
act( "&g$n removes $p from the trade.", ch, obj, victim, TO_VICT );
return;
}
if( !str_cmp( arg, "lock" ) )
{
if( IS_SET( ch->pcdata->trade->flags, TRADE_LOCKED ) )
{
REMOVE_BIT( ch->pcdata->trade->flags, TRADE_LOCKED );
REMOVE_BIT( ch->pcdata->trade->flags, TRADE_AGREED );
REMOVE_BIT( victim->pcdata->trade->flags, TRADE_AGREED );
send_to_char( "&GYou unlock the trade.&n\n\r", ch );
act( "&G$n unlocks the trade.", ch, NULL, victim, TO_VICT );
return;
}
send_to_char( "&GYou lock the trade.&n\n\r", ch );
act( "&G$n locks the trade.", ch, NULL, victim, TO_VICT );
SET_BIT( ch->pcdata->trade->flags, TRADE_LOCKED );
return;
}
if( !str_cmp( arg, "agree" ) || !str_cmp( arg, "accept" ) )
{
if( !IS_SET( ch->pcdata->trade->flags, TRADE_LOCKED )
|| !IS_SET( victim->pcdata->trade->flags, TRADE_LOCKED ) )
{
send_to_char( "&rBoth parties must lock the trade first.&n\n\r", ch );
return;
}
if( IS_SET( ch->pcdata->trade->flags, TRADE_AGREED ) )
{
REMOVE_BIT( ch->pcdata->trade->flags, TRADE_AGREED );
send_to_char( "&GYou withdraw your agreement to the trade.&n\n\r",
ch );
act( "&G$n removes $s agreement to the trade.",
ch, NULL, victim, TO_VICT );
return;
}
if( !IS_SET( victim->pcdata->trade->flags, TRADE_AGREED ) )
{
SET_BIT( ch->pcdata->trade->flags, TRADE_AGREED );
send_to_char( "&GYou signify your agreement for this trade.&n\n\r", ch );
act( "&G$n has agreed to the trade.", ch, NULL, victim, TO_VICT );
return;
}
if( check_trade( ch, victim ) && check_trade( victim, ch ) )
{
affect_trade( ch, victim );
affect_trade( victim, ch );
act( "&GYou shake $N's hand and seal the deal.",
ch, NULL, victim, TO_CHAR );
act( "&G$n closes the deal, you shake $s hand and seal the deal.",
ch, NULL, victim, TO_VICT );
act( "&G$n has just closed the deal with $N.",
ch, NULL, victim, TO_NOTVICT );
}
else
{
ch->gold += ch->pcdata->trade->gold;
victim->gold += victim->pcdata->trade->gold;
}
free_mem( ch->pcdata->trade->other, sizeof( TRADE_DATA ) );
free_mem( ch->pcdata->trade, sizeof( TRADE_DATA ) );
ch->pcdata->trade = NULL;
victim->pcdata->trade = NULL;
return;
}
send_to_char( "Type HELP TRADE to get more information on trading securely.\n\r", ch );
return;
}