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