/*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ***************************************************************************/ #include <sys/types.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <time.h> #include "merc.h" /* * Local functions. */ bool is_note_to args( ( CHAR_DATA *ch, NOTE_DATA *pnote ) ); void note_attach args( ( CHAR_DATA *ch ) ); void note_remove args( ( CHAR_DATA *ch, NOTE_DATA *pnote ) ); bool is_note_to( CHAR_DATA *ch, NOTE_DATA *pnote ) { if ( !str_cmp( ch->name, pnote->sender ) ) return TRUE; if ( is_name( "all", pnote->to_list ) ) return TRUE; if ( ch->level >= MAX_LEVEL - 4 && is_name( "immortal", pnote->to_list ) ) return TRUE; if ( is_name( ch->name, pnote->to_list ) ) return TRUE; return FALSE; } void note_attach( CHAR_DATA *ch ) { NOTE_DATA *pnote; if ( ch->pnote != NULL ) return; if ( note_free == NULL ) { pnote = alloc_mem( sizeof(*ch->pnote) ); } else { pnote = note_free; note_free = note_free->next; } pnote->next = NULL; pnote->sender = str_dup( ch->name ); pnote->date = str_dup( "" ); pnote->to_list = str_dup( "" ); pnote->subject = str_dup( "" ); pnote->text = str_dup( "" ); ch->pnote = pnote; return; } void note_remove( CHAR_DATA *ch, NOTE_DATA *pnote ) { char to_new[MAX_INPUT_LENGTH]; char to_one[MAX_INPUT_LENGTH]; FILE *fp; NOTE_DATA *prev; char *to_list; /* * Build a new to_list. * Strip out this recipient. */ to_new[0] = '\0'; to_list = pnote->to_list; while ( *to_list != '\0' ) { to_list = one_argument( to_list, to_one ); if ( to_one[0] != '\0' && str_cmp( ch->name, to_one ) ) { strcat( to_new, " " ); strcat( to_new, to_one ); } } /* * Just a simple recipient removal? */ if ( str_cmp( ch->name, pnote->sender ) && to_new[0] != '\0' ) { free_mem( pnote->to_list ); pnote->to_list = str_dup( to_new + 1 ); return; } /* * Remove note from linked list. */ if ( pnote == note_list ) { note_list = pnote->next; } else { for ( prev = note_list; prev != NULL; prev = prev->next ) { if ( prev->next == pnote ) break; } if ( prev == NULL ) { bug( "Note_remove: pnote not found.", 0 ); return; } prev->next = pnote->next; } free_mem( pnote->text ); free_mem( pnote->subject ); free_mem( pnote->to_list ); free_mem( pnote->date ); free_mem( pnote->sender ); pnote->next = note_free; note_free = pnote; /* * Rewrite entire list. */ fclose( fpReserve ); if ( ( fp = fopen( NOTE_FILE, "w" ) ) == NULL ) { perror( NOTE_FILE ); } else { for ( pnote = note_list; pnote != NULL; pnote = pnote->next ) { fprintf( fp, "Sender %s~\nDate %s~\nTo %s~\nSubject %s~\nText\n%s~\n\n", pnote->sender, pnote->date, pnote->to_list, pnote->subject, pnote->text ); } fclose( fp ); } fpReserve = fopen( NULL_FILE, "r" ); return; } void do_note( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; char arg[MAX_INPUT_LENGTH]; NOTE_DATA *pnote; int vnum; int anum; if ( IS_NPC(ch) ) return; argument = one_argument( argument, arg ); smash_tilde( argument ); if ( !str_cmp( arg, "list" ) ) { vnum = 0; for ( pnote = note_list; pnote != NULL; pnote = pnote->next ) { if ( is_note_to( ch, pnote ) ) { sprintf( buf, "[%3d] %s: %s\n\r", vnum, pnote->sender, pnote->subject ); send_to_char( buf, ch ); vnum++; } } return; } if ( !str_cmp( arg, "read" ) ) { bool fAll; if ( !str_cmp( argument, "all" ) ) { fAll = TRUE; anum = 0; } else if ( is_number( argument ) ) { fAll = FALSE; anum = atoi( argument ); } else { send_to_char( "Note read which number?\n\r", ch ); return; } vnum = 0; for ( pnote = note_list; pnote != NULL; pnote = pnote->next ) { if ( is_note_to( ch, pnote ) && ( vnum++ == anum || fAll ) ) { sprintf( buf, "[%3d] %s: %s\n\r%s\n\rTo: %s\n\r", vnum - 1, pnote->sender, pnote->subject, pnote->date, pnote->to_list ); send_to_char( buf, ch ); send_to_char( pnote->text, ch ); return; } } send_to_char( "No such note.\n\r", ch ); return; } if ( !str_cmp( arg, "+" ) ) { note_attach( ch ); strcpy( buf, ch->pnote->text ); if ( strlen(buf) + strlen(argument) >= MAX_STRING_LENGTH - 2 ) { send_to_char( "Note too long.\n\r", ch ); return; } strcat( buf, argument ); strcat( buf, "\n\r" ); free_mem( ch->pnote->text ); ch->pnote->text = str_dup( buf ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg, "subject" ) ) { note_attach( ch ); free_mem( ch->pnote->subject ); ch->pnote->subject = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg, "to" ) ) { note_attach( ch ); free_mem( ch->pnote->to_list ); ch->pnote->to_list = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg, "clear" ) ) { if ( ch->pnote != NULL ) { free_mem( ch->pnote->text ); free_mem( ch->pnote->subject ); free_mem( ch->pnote->to_list ); free_mem( ch->pnote->date ); free_mem( ch->pnote->sender ); ch->pnote->next = note_free; note_free = ch->pnote; ch->pnote = NULL; } send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg, "show" ) ) { if ( ch->pnote == NULL ) { send_to_char( "You have no note in progress.\n\r", ch ); return; } sprintf( buf, "%s: %s\n\rTo: %s\n\r", ch->pnote->sender, ch->pnote->subject, ch->pnote->to_list ); send_to_char( buf, ch ); send_to_char( ch->pnote->text, ch ); return; } if ( !str_cmp( arg, "post" ) ) { FILE *fp; char *strtime; if ( ch->pnote == NULL ) { send_to_char( "You have no note in progress.\n\r", ch ); return; } ch->pnote->next = NULL; strtime = ctime( ¤t_time ); strtime[strlen(strtime)-1] = '\0'; ch->pnote->date = str_dup( strtime ); if ( note_list == NULL ) { note_list = ch->pnote; } else { for ( pnote = note_list; pnote->next != NULL; pnote = pnote->next ) ; pnote->next = ch->pnote; } pnote = ch->pnote; ch->pnote = NULL; fclose( fpReserve ); if ( ( fp = fopen( NOTE_FILE, "a" ) ) == NULL ) { perror( NOTE_FILE ); } else { fprintf( fp, "Sender %s~\nDate %s~\nTo %s~\nSubject %s~\nText\n%s~\n\n", pnote->sender, pnote->date, pnote->to_list, pnote->subject, pnote->text ); fclose( fp ); } fpReserve = fopen( NULL_FILE, "r" ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg, "remove" ) ) { if ( !is_number( argument ) ) { send_to_char( "Note remove which number?\n\r", ch ); return; } anum = atoi( argument ); vnum = 0; for ( pnote = note_list; pnote != NULL; pnote = pnote->next ) { if ( is_note_to( ch, pnote ) && vnum++ == anum ) { note_remove( ch, pnote ); send_to_char( "Ok.\n\r", ch ); return; } } send_to_char( "No such note.\n\r", ch ); return; } send_to_char( "Huh? Type 'help note' for usage.\n\r", ch ); return; } void do_auction( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; DESCRIPTOR_DATA *d; if ( argument[0] == '\0' ) { if ( IS_NPC(ch) ) return; if ( IS_SET(ch->act, PLR_NO_AUCTION) ) { REMOVE_BIT(ch->act, PLR_NO_AUCTION); send_to_char( "You hear auctions again.\n\r", ch ); } else { SET_BIT(ch->act, PLR_NO_AUCTION); send_to_char( "You won't hear auctions.\n\r", ch ); } return; } REMOVE_BIT(ch->act, PLR_NO_AUCTION); act( "You auction '$T'.", ch, NULL, argument, TO_CHAR ); sprintf( buf, "$n auctions '%s'.", argument ); for ( d = descriptor_list; d != NULL; d = d->next ) { CHAR_DATA *victim; victim = d->original ? d->original : d->character; if ( d->connected != CON_PLAYING || d->character == ch || IS_SET(victim->act, PLR_NO_AUCTION) ) continue; act( buf, ch, NULL, d->character, TO_VICT ); } return; } void do_chat( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; DESCRIPTOR_DATA *d; if ( argument[0] == '\0' ) { if ( IS_NPC(ch) ) return; if ( IS_SET(ch->act, PLR_NO_CHAT) ) { REMOVE_BIT(ch->act, PLR_NO_CHAT); send_to_char( "You hear chat again.\n\r", ch ); } else { SET_BIT(ch->act, PLR_NO_CHAT); send_to_char( "You won't hear chat.\n\r", ch ); } return; } REMOVE_BIT(ch->act, PLR_NO_CHAT); act( "You chat '$T'.", ch, NULL, argument, TO_CHAR ); sprintf( buf, "$n chats '%s'.", argument ); for ( d = descriptor_list; d != NULL; d = d->next ) { CHAR_DATA *victim; victim = d->original ? d->original : d->character; if ( d->connected != CON_PLAYING || d->character == ch || IS_SET(victim->act, PLR_NO_CHAT) ) continue; act( buf, ch, NULL, d->character, TO_VICT ); } return; } void do_immtalk( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; DESCRIPTOR_DATA *d; if ( argument[0] == '\0' ) { send_to_char( "Immtalk what?\n\r", ch ); return; } sprintf( buf, "$n: %s.", argument ); act( buf, ch, NULL, NULL, TO_CHAR ); for ( d = descriptor_list; d != NULL; d = d->next ) { if ( d->connected == CON_PLAYING || ( d->original ? d->original->level : d->character->level ) >= MAX_LEVEL-4 ) act( buf, ch, NULL, d->character, TO_VICT ); } return; } void do_say( CHAR_DATA *ch, char *argument ) { if ( argument[0] == '\0' ) { send_to_char( "Say what?\n\r", ch ); return; } act( "$n says '$T'.", ch, NULL, argument, TO_ROOM ); act( "You say '$T'.", ch, NULL, argument, TO_CHAR ); return; } void do_shout( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; DESCRIPTOR_DATA *d; if ( !IS_NPC(ch) && IS_SET(ch->act, PLR_NO_SHOUT) ) { send_to_char( "You can't shout.\n\r", ch ); return; } if ( argument[0] == '\0' ) { send_to_char( "Shout what?\n\r", ch ); return; } WAIT_STATE( ch, 12 ); act( "You shout '$T'.", ch, NULL, argument, TO_CHAR ); sprintf( buf, "$n shouts '%s'.", argument ); for ( d = descriptor_list; d != NULL; d = d->next ) { CHAR_DATA *victim; victim = d->original ? d->original : d->character; if ( d->connected != CON_PLAYING || d->character == ch || IS_SET(victim->act, PLR_NO_SHOUT) ) continue; act( buf, ch, NULL, d->character, TO_VICT ); } return; } void do_tell( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; if ( !IS_NPC(ch) && IS_SET(ch->act, PLR_NO_TELL) ) { send_to_char( "Your message didn't get through.\n\r", ch ); return; } argument = one_argument( argument, arg ); if ( arg[0] == '\0' || argument[0] == '\0' ) { send_to_char( "Tell whom what?\n\r", ch ); return; } /* * Can tell to PC's anywhere, but NPC's only in same room. * -- Furey */ if ( ( victim = get_char_world( ch, arg ) ) == NULL || ( IS_NPC(victim) && victim->in_room != ch->in_room ) ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( ch->level < MAX_LEVEL-3 && !IS_AWAKE(victim) ) { act( "$E can't hear you.", ch, 0, victim, TO_CHAR ); return; } victim->reply = ch; sprintf( buf, "$n tells you '%s'.", argument ); act( buf, ch, NULL, victim, TO_VICT ); sprintf( buf, "You tell $N '%s'.", argument ); act( buf, ch, NULL, victim, TO_CHAR ); return; } void do_reply( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; CHAR_DATA *victim; if ( !IS_NPC(ch) && IS_SET(ch->act, PLR_NO_TELL) ) { send_to_char( "Your message didn't get through.\n\r", ch ); return; } if ( ( victim = ch->reply ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( ch->level < MAX_LEVEL-3 && !IS_AWAKE(victim) ) { act( "$E can't hear you.", ch, 0, victim, TO_CHAR ); return; } victim->reply = ch; sprintf( buf, "$n tells you '%s'.", argument ); act( buf, ch, NULL, victim, TO_VICT ); sprintf( buf, "You tell $N '%s'.", argument ); act( buf, ch, NULL, victim, TO_CHAR ); return; } void do_yell( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; DESCRIPTOR_DATA *d; int area; if ( argument[0] == '\0' ) { send_to_char( "Yell what?\n\r", ch ); return; } area = room_index[ch->in_room].area; act( "You yell '$T'.", ch, NULL, argument, TO_CHAR ); sprintf( buf, "$n yells '%s'.", argument ); for ( d = descriptor_list; d != NULL; d = d->next ) { if ( d->connected != CON_PLAYING || d->character == ch || room_index[d->character->in_room].area != area ) continue; act( buf, ch, NULL, d->character, TO_VICT ); } return; } void do_emote( CHAR_DATA *ch, char *argument ) { if ( !IS_NPC(ch) && IS_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; } act( "$n $T.", ch, NULL, argument, TO_ROOM ); act( "$n $T.", ch, NULL, argument, TO_CHAR ); return; } /* * All the posing stuff. */ struct pose_table_type { char * message[2*MAX_CLASS]; }; const struct pose_table_type pose_table [] = { { { "You sizzle with energy.", "$n sizzles with energy.", "You feel very holy.", "$n looks very holy.", "You perform a small card trick.", "$n performs a small card trick.", "You show your bulging muscles.", "$n shows $s bulging muscles." } }, { { "You turn into a butterfly, then return to your normal shape.", "$n turns into a butterfly, then returns to $s normal shape.", "You nonchalantly turn wine into water.", "$n nonchalantly turns wine into water.", "You wiggle your ears alternately.", "$n wiggles $s ears alternately.", "You crack nuts between your fingers.", "$n cracks nuts between $s fingers." } }, { { "Blue sparks fly from your fingers.", "Blue sparks fly from $n's fingers.", "A halo appears over your head.", "A halo appears over $n's head.", "You nimbly tie yourself into a knot.", "$n nimbly ties $mself into a knot.", "You grizzle your teeth and look mean.", "$n grizzles $s teeth and looks mean." } }, { { "Little red lights dance in your eyes.", "Little red lights dance in $n's eyes.", "You recite words of wisdom.", "$n recites words of wisdom.", "You juggle with daggers, apples, and eyeballs.", "$n juggles with daggers, apples, and eyeballs.", "You hit your head, and your eyes roll.", "$n hits $s head, and $s eyes roll." } }, { { "A slimy green monster appears before you and bows.", "A slimy green monster appears before $n and bows.", "Deep in prayer, you levitate.", "Deep in prayer, $n levitates.", "You steal the underwear off every person in the room.", "Your underwear is gone! $n stole it!", "Crunch, crunch -- you munch a bottle.", "Crunch, crunch -- $n munches a bottle." } }, { { "You turn everybody into a little pink elephant.", "You are turned into a little pink elephant by $n.", "An angel consults you.", "An angel consults $n.", "The dice roll ... and you win again.", "The dice roll ... and $n wins again.", "... 98, 99, 100 ... you do pushups.", "... 98, 99, 100 ... $n does pushups." } }, { { "A small ball of light dances on your fingertips.", "A small ball of light dances on $n's fingertips.", "Your body glows with an unearthly light.", "$n's body glows with an unearthly light.", "You count the money in everyone's pockets.", "Check your money, $n is counting it.", "Arnold Schwarzenegger admires your physique.", "Arnold Schwarzenegger admires $n's physique." } }, { { "Smoke and fumes leak from your nostrils.", "Smoke and fumes leak from $n's nostrils.", "A spot light hits you.", "A spot light hits $n.", "You balance a pocket knife on your tongue.", "$n balances a pocket knife on your tongue.", "Watch your feet, you are juggling granite boulders.", "Watch your feet, $n is juggling granite boulders." } }, { { "The light flickers as you rap in magical languages.", "The light flickers as $n raps in magical languages.", "Everyone levitates as you pray.", "You levitate as $n prays.", "You produce a coin from everyone's ear.", "$n produces a coin from your ear.", "Oomph! You squeeze water out of a granite boulder.", "Oomph! $n squeezes water out of a granite boulder." } }, { { "Your head disappears.", "$n's head disappears.", "A cool breeze refreshes you.", "A cool breeze refreshes $n.", "You step behind your shadow.", "$n steps behind $s shadow.", "You pick your teeth with a spear.", "$n picks $s teeth with a spear." } }, { { "A fire elemental singes your hair.", "A fire elemental singes $n's hair.", "The sun pierces through the clouds to illuminate you.", "The sun pierces through the clouds to illuminate $n.", "Your eyes dance with greed.", "$n's eyes dance with greed.", "Everyone is swept off their foot by your hug.", "You are swept off your feet by $n's hug." } }, { { "The sky changes color to match your eyes.", "The sky changes color to match $n's eyes.", "The ocean parts before you.", "The ocean parts before $n.", "You deftly steal everyone's weapon.", "$n deftly steals your weapon.", "Your karate chop splits a tree.", "$n's karate chop splits a tree." } }, { { "The stones dance to your command.", "The stones dance to $n's command.", "A thunder cloud kneels to you.", "A thunder cloud kneels to $n.", "The Grey Mouser buys you a beer.", "The Grey Mouser buys $n a beer.", "A strap of your armor breaks over your mighty thews.", "A strap of $n's armor breaks over $s mighty thews." } }, { { "The heavens and grass change colour as you smile.", "The heavens and grass change colour as $n smiles.", "The Burning Man speaks to you.", "The Burning Man speaks to $n.", "Everyone's pocket explodes with your fireworks.", "Your pocket explodes with $n's fireworks.", "A boulder cracks at your frown.", "A boulder cracks at $n's frown." } }, { { "Everyone's clothes are transparent, and you are laughing.", "Your clothes are transparent, and $n is laughing.", "An eye in a pyramid winks at you.", "An eye in a pyramid winks at $n.", "Everyone discovers your dagger a centimeter from their eye.", "You discover $n's dagger a centimeter from your eye.", "Mercenaries arrive to do your bidding.", "Mercenaries arrive to do $n's bidding." } }, { { "A black hole swallows you.", "A black hole swallows $n.", "Valentine Michael Smith offers you a glass of water.", "Valentine Michael Smith offers $n a glass of water.", "Where did you go?", "Where did $n go?", "Four matched Percherons bring in your chariot.", "Four matched Percherons bring in $n's chariot." } }, { { "The world shimmers in time with your whistling.", "The world shimmers in time with $n's whistling.", "The great god Mota gives you a staff.", "The great god Mota gives $n a staff.", "Click.", "Click.", "Atlas asks you to relieve him.", "Atlas asks $n to relieve him." } } }; void do_pose( CHAR_DATA *ch, char *argument ) { int level; int pose; if ( IS_NPC(ch) ) return; level = MIN( ch->level, sizeof(pose_table) / sizeof(pose_table[0]) ); pose = number_range(0, level); act( pose_table[pose].message[2*ch->class+0], ch, NULL, NULL, TO_CHAR ); act( pose_table[pose].message[2*ch->class+1], ch, NULL, NULL, TO_ROOM ); return; } void do_bug( CHAR_DATA *ch, char *argument ) { append_file( ch, BUG_FILE, argument ); send_to_char( "Ok. Thanks.\n\r", ch ); return; } void do_idea( CHAR_DATA *ch, char *argument ) { append_file( ch, IDEA_FILE, argument ); send_to_char( "Ok. Thanks.\n\r", ch ); return; } void do_typo( CHAR_DATA *ch, char *argument ) { append_file( ch, TYPO_FILE, argument ); send_to_char( "Ok. Thanks.\n\r", ch ); return; } void do_autoexit( CHAR_DATA *ch, char *argument ) { if ( IS_NPC(ch) ) return; if ( IS_SET(ch->act, PLR_AUTOEXIT) ) { send_to_char( "Autoexit mode off.\n\r", ch ); REMOVE_BIT(ch->act, PLR_AUTOEXIT); } else { send_to_char( "Autoexit mode on.\n\r", ch ); SET_BIT(ch->act, PLR_AUTOEXIT); } return; } void do_autoloot( CHAR_DATA *ch, char *argument ) { if ( IS_NPC(ch) ) return; if ( IS_SET(ch->act, PLR_AUTOLOOT) ) { send_to_char( "Autoloot mode off.\n\r", ch ); REMOVE_BIT(ch->act, PLR_AUTOLOOT); } else { send_to_char( "Autoloot mode on.\n\r", ch ); SET_BIT(ch->act, PLR_AUTOLOOT); } return; } void do_autosac( CHAR_DATA *ch, char *argument ) { if ( IS_NPC(ch) ) return; if ( IS_SET(ch->act, PLR_AUTOSAC) ) { send_to_char( "Autosac mode off.\n\r", ch ); REMOVE_BIT(ch->act, PLR_AUTOSAC); } else { send_to_char( "Autosac mode on.\n\r", ch ); SET_BIT(ch->act, PLR_AUTOSAC); } return; } void do_brief( CHAR_DATA *ch, char *argument ) { if ( IS_NPC(ch) ) return; if ( IS_SET(ch->act, PLR_BRIEF) ) { send_to_char( "Brief mode off.\n\r", ch ); REMOVE_BIT(ch->act, PLR_BRIEF); } else { send_to_char( "Brief mode on.\n\r", ch ); SET_BIT(ch->act, PLR_BRIEF); } return; } void do_blank( CHAR_DATA *ch, char *argument ) { if ( IS_NPC(ch) ) return; if (IS_SET(ch->act, PLR_NO_BLANK) ) { send_to_char( "Blank mode on.\n\r", ch ); REMOVE_BIT(ch->act, PLR_NO_BLANK); } else { send_to_char( "Blank mode off.\n\r", ch ); SET_BIT(ch->act, PLR_NO_BLANK); } return; } void do_prompt( CHAR_DATA *ch, char *argument ) { if ( IS_NPC(ch) ) return; if ( IS_SET( ch->act, PLR_NO_PROMPT ) ) { send_to_char( "Prompt mode on.\n\r", ch ); REMOVE_BIT( ch->act, PLR_NO_PROMPT ); } else { send_to_char( "Prompt mode off.\n\r", ch ); SET_BIT( ch->act, PLR_NO_PROMPT ); } return; } void do_rent( CHAR_DATA *ch, char *argument ) { send_to_char( "There is no rent here. Just save and quit.\n\r", ch ); return; } void do_qui( CHAR_DATA *ch, char *argument ) { send_to_char( "If you want to QUIT, you have to spell it out.\n\r", ch ); return; } void do_quit( CHAR_DATA *ch, char *argument ) { DESCRIPTOR_DATA *d; if ( IS_NPC(ch) ) return; if ( ch->position == POS_FIGHTING ) { send_to_char( "No way! You are fighting.\n\r", ch ); return; } if ( ch->position < POS_STUNNED ) { send_to_char( "You're not DEAD yet.\n\r", ch ); return; } send_to_char( "Had I but time--as this fell sergeant, Death,\n\rIs strict in his arrest--O, I could tell you--\n\rBut let it be.\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 ); /* * After extract_char the ch is no longer valid! */ save_char_obj( ch ); d = ch->desc; extract_char( ch, TRUE ); if ( d != NULL ) close_socket( d ); return; } void do_save( CHAR_DATA *ch, char *argument ) { if ( IS_NPC(ch) ) return; if ( ch->level < 2 ) { send_to_char( "You must be at least second level to save.\n\r", ch ); return; } save_char_obj( ch ); send_to_char( "Ok.\n\r", ch ); return; } void do_not_here( CHAR_DATA *ch, char *argument ) { send_to_char( "Sorry, you cannot do that here.\n\r", ch ); return; } void do_follow( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Follow whom?\n\r", ch ); return; } if ( ( victim = get_char_room( ch, arg ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master != NULL ) { act( "But you'd rather follow $N!", ch, NULL, ch->master, TO_CHAR ); return; } if ( victim == ch ) { if ( ch->master == NULL ) { send_to_char( "You already follow yourself.\n\r", ch ); return; } stop_follower( ch ); return; } if ( ( ch->level - victim->level < -5 || ch->level - victim->level > 5 ) && ch->level < MAX_LEVEL-3 ) { send_to_char( "You are not of the right caliber to follow.\n\r", ch ); return; } if ( ch->master != NULL ) stop_follower( ch ); add_follower( ch, victim ); return; } void add_follower( CHAR_DATA *ch, CHAR_DATA *master ) { if ( ch->master != NULL ) { bug( "Add_follower: non-null master.", 0 ); 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 == NULL ) { bug( "Stop_follower: null master.", 0 ); return; } if ( IS_AFFECTED(ch, AFF_CHARM) ) { REMOVE_BIT( ch->affected_by, AFF_CHARM ); affect_strip( ch, gsn_charm_person ); } 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_DATA *fch; if ( ch->master != NULL ) stop_follower( ch ); ch->leader = NULL; for ( fch = char_list; fch != NULL; fch = fch->next ) { if ( fch->master == ch ) stop_follower( fch ); if ( fch->leader == ch ) fch->leader = fch; } return; } void do_order( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; CHAR_DATA *och; CHAR_DATA *och_next; bool found; 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" ) ) { victim = NULL; } else { if ( ( victim = get_char_room( ch, arg ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( victim == ch ) { send_to_char( "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 = room_index[ch->in_room].people; och != NULL; och = och_next ) { och_next = och->next_in_room; if ( !IS_AFFECTED(och, AFF_CHARM) || och->master != ch ) continue; if ( victim == NULL || victim == och ) { found = TRUE; sprintf( buf, "$n orders you to '%s'.", argument ); act( buf, ch, NULL, 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, char *argument ) { char buf[MAX_STRING_LENGTH]; char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; one_argument( argument, arg ); if ( arg[0] == '\0' ) { CHAR_DATA *gch; CHAR_DATA *leader; leader = ch->leader ? ch->leader : ch; sprintf( buf, "%s's group:\n\r", PERS(leader, ch) ); send_to_char( buf, ch ); for ( gch = char_list; gch != NULL; gch = gch->next ) { if ( is_same_group( gch, ch ) ) { sprintf( buf, "[%2d %s] %-12s %4d/%4d hp %4d/%4d mana %4d/%4d mv %5d xp\n\r", gch->level, IS_NPC(gch) ? "Mob" : class_table[gch->class].who_name, PERS(gch, ch), gch->hit, gch->max_hit, gch->mana, gch->max_mana, gch->move, gch->max_move, gch->exp ); send_to_char( buf, ch ); } } return; } if ( ( victim = get_char_room( ch, arg ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( ch->master != NULL || ( ch->leader != NULL && 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( "$n removes $N from $s group.", ch, NULL, victim, TO_NOTVICT ); act( "$n removes you from $s group.", ch, NULL, victim, TO_VICT ); act( "You remove $N from your group.", ch, NULL, victim, TO_CHAR ); return; } if ( ch->level - victim->level < -5 || ch->level - victim->level > 5 ) { act( "$N cannot join $n's group.", ch, NULL, victim, TO_NOTVICT ); act( "You cannot join $n's group.", ch, NULL, victim, TO_VICT ); act( "$N cannot join your group.", ch, NULL, victim, TO_CHAR ); return; } victim->leader = ch; act( "$N joins $n's group.", ch, NULL, victim, TO_NOTVICT ); act( "You join $n's group.", ch, NULL, victim, TO_VICT ); act( "$N joins your group.", ch, NULL, victim, TO_CHAR ); return; } void do_split( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; char arg[MAX_INPUT_LENGTH]; CHAR_DATA *gch; 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( 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 = room_index[ch->in_room].people; gch; gch = gch->next_in_room ) { if ( is_same_group( gch, ch ) ) members++; } if ( members < 2 ) { 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; sprintf( buf, "You split %d gold coins. Your share is %d gold coins.\n\r", amount, share + extra ); send_to_char( buf, ch ); sprintf( buf, "%s splits %d gold coins. Your share is %d gold coins.\n\r", ch->name, amount, share ); for ( gch = room_index[ch->in_room].people; gch; gch = gch->next_in_room ) { if ( gch != ch && is_same_group( gch, ch ) ) { send_to_char( buf, gch ); gch->gold += share; } } return; } void do_gtell( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; CHAR_DATA *gch; if ( argument[0] == '\0' ) { send_to_char( "Tell your group what?\n\r", ch ); return; } if ( IS_SET( ch->act, PLR_NO_TELL ) ) { send_to_char( "Your message didn't get through!\n\r", ch ); return; } sprintf( buf, "%s tells the group, '%s'.\n\r", ch->name, argument ); for ( gch = char_list; gch != NULL; gch = gch->next ) { if ( is_same_group( gch, ch ) ) send_to_char( buf, gch ); } 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->leader ) ach = ach->leader; if ( bch->leader ) bch = bch->leader; return ach == bch; }