/***************************************************************************
* 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. *
***************************************************************************/
#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.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, int spool ) );
void note_remove args( ( CHAR_DATA *ch, NOTE_DATA *pnote, int spool ) );
void talk_channel args( ( CHAR_DATA *ch, char *argument,
int channel, const char *verb ) );
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( IS_HERO( ch )
&& is_name( "immortal", pnote->to_list ) )
return TRUE;
if( is_name_old( ch->name, pnote->to_list ) )
return TRUE;
return FALSE;
}
void note_attach( CHAR_DATA *ch, int spool )
{
NOTE_DATA *pnote;
if( ch->pnote )
return;
if( !note_free )
{
pnote = alloc_perm( sizeof( *ch->pnote ) );
}
else
{
pnote = note_free;
note_free = note_free->next;
}
pnote->next = NULL;
pnote->spool = spool;
pnote->anon = FALSE;
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, int spool )
{
NOTE_DATA *prev;
FILE *fp;
char *to_list;
char to_new[ MAX_INPUT_LENGTH ];
char to_one[ MAX_INPUT_LENGTH ];
char buf[ MAX_STRING_LENGTH ];
switch( spool )
{
case( SPOOL_NOTE ):
sprintf( buf, "note" );
break;
case( SPOOL_IDEA ):
sprintf( buf, "idea" );
break;
case( SPOOL_MAIL ):
sprintf( buf, "mail" );
break;
case( SPOOL_BUG ):
sprintf( buf, "bug" );
break;
case( SPOOL_QUEST ):
sprintf( buf, "qwest" );
break;
default:
sprintf( buf, "note" );
break;
}
/*
* 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_string( 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 ; prev = prev->next )
{
if( prev->next == pnote )
break;
}
if( !prev )
{
bug( "Note_remove: pnote not found.", 0 );
return;
}
prev->next = pnote->next;
}
free_string( pnote->text );
free_string( pnote->subject );
free_string( pnote->to_list );
free_string( pnote->date );
free_string( pnote->sender );
pnote->spool = SPOOL_NOTE;
pnote->anon = FALSE;
pnote->next = note_free;
note_free = pnote;
/*
* Rewrite entire list.
*/
fclose( fpReserve );
if( !( fp = fopen( NOTE_FILE, "w" ) ) )
{
perror( NOTE_FILE );
}
else
{
for( pnote = note_list ; pnote ; pnote = pnote->next )
{
fprintf( fp, "Sender %s~\n", pnote->sender );
fprintf( fp, "Spool %d\n", pnote->spool );
fprintf( fp, "Anon %d\n", pnote->anon );
fprintf( fp, "Date %s~\n", pnote->date );
fprintf( fp, "Stamp %ld\n", pnote->date_stamp );
fprintf( fp, "To %s~\n", pnote->to_list );
fprintf( fp, "Subject %s~\n", pnote->subject );
fprintf( fp, "Text\n%s~\n\n", pnote->text );
}
fclose( fp );
}
fpReserve = fopen( NULL_FILE, "r" );
return;
}
void do_note( CHAR_DATA *ch, char *argument )
{
note_process( ch, argument, SPOOL_NOTE );
}
void do_idea( CHAR_DATA *ch, char *argument )
{
note_process( ch, argument, SPOOL_IDEA );
}
void do_mail( CHAR_DATA *ch, char *argument )
{
note_process( ch, argument, SPOOL_MAIL );
}
void do_bug( CHAR_DATA *ch, char *argument )
{
note_process( ch, argument, SPOOL_BUG );
}
void do_qwest( CHAR_DATA *ch, char *argument )
{
note_process( ch, argument, SPOOL_QUEST );
}
void note_process( CHAR_DATA *ch, char *argument, int spool )
{
NOTE_DATA *pnote;
char *buf1;
char buf[ MAX_STRING_LENGTH ];
char buf2[ MAX_STRING_LENGTH ];
char spoolbuf[ MAX_STRING_LENGTH ];
char arg[ MAX_INPUT_LENGTH ];
int vnum;
int anum;
if( IS_NPC( ch ) )
return;
buf1 = NULL;
argument = one_argument( argument, arg );
smash_tilde( argument );
switch( spool )
{
case( SPOOL_NOTE ):
sprintf( buf2, "note" );
break;
case( SPOOL_IDEA ):
sprintf( buf2, "idea" );
break;
case( SPOOL_MAIL ):
sprintf( buf2, "mail" );
break;
case( SPOOL_BUG ):
sprintf( buf2, "bug" );
break;
case( SPOOL_QUEST ):
sprintf( buf2, "qwest" );
break;
default:
sprintf( buf2, "note" );
break;
}
if( !*arg )
{
switch( spool )
{
case SPOOL_NOTE:
do_note( ch, "read" );
break;
case SPOOL_IDEA:
do_idea( ch, "read" );
break;
case SPOOL_BUG:
do_bug( ch, "read" );
break;
case SPOOL_QUEST:
do_qwest( ch, "read" );
break;
case SPOOL_MAIL:
do_mail( ch, "read" );
break;
default:
return;
}
return;
}
if( ( !str_prefix( arg, "list" ) ) )
{
vnum = 0;
buf1 = NULL;
for( pnote = note_list ; pnote ; pnote = pnote->next )
{
if( ( is_note_to( ch, pnote ) ) && ( spool == pnote->spool ) )
{
if( pnote->anon )
{
sprintf( buf, "[{g%3d{r%s{x] {cAnonymous{x: %s\n\r",
vnum,
( pnote->date_stamp > ch->last_note[spool]
&& str_cmp( pnote->sender, ch->name ) ) ? "N" : " ",
pnote->subject );
}
else
{
sprintf( buf, "[{g%3d{r%s{x] {c%s{x: %s\n\r",
vnum,
( pnote->date_stamp > ch->last_note[ spool ]
&& str_cmp( pnote->sender, ch->name ) ) ? "N" : " ",
pnote->sender, pnote->subject );
}
str_cat( &buf1, buf );
vnum++;
}
}
page_to_char( buf1, ch );
free( buf1 );
return;
}
if( !str_prefix( arg, "read" ) )
{
bool fAll;
if( !str_cmp( argument, "all" ) )
{
fAll = TRUE;
anum = 0;
}
else if( !*argument || !str_prefix( argument, "next" ) )
/* read next unread note */
{
vnum = 0;
buf1 = NULL;
for( pnote = note_list ; pnote ; pnote = pnote->next )
{
if( is_note_to( ch, pnote )
&& str_cmp( ch->name, pnote->sender )
&& ch->last_note[spool] < pnote->date_stamp
&& pnote->spool == spool )
{
if( pnote->anon )
{
sprintf( buf, "[{g%3d{x] {cAnonymous{x: %s\n\r%s\n\rTo: %s\n\r",
vnum,
pnote->subject,
pnote->date,
pnote->to_list );
}
else
{
sprintf( buf, "[{g%3d{x] {c%s{x: %s\n\r%s\n\rTo: %s\n\r",
vnum,
pnote->sender,
pnote->subject,
pnote->date,
pnote->to_list );
}
str_cat( &buf1, buf );
str_cat( &buf1, pnote->text );
ch->last_note[spool] = UMAX( ch->last_note[spool],
pnote->date_stamp );
page_to_char( buf1, ch );
free( buf1 );
return;
}
else if( pnote->spool == spool )
vnum++;
}
sprintf( spoolbuf, "You have no unread %ss.\n\r", buf2 );
send_to_char_bw( spoolbuf, ch );
return;
}
else if( is_number( argument ) )
{
fAll = FALSE;
anum = atoi( argument );
}
else
{
sprintf( spoolbuf, "%s read which number\n\r", buf2 );
spoolbuf[0] = UPPER( spoolbuf[0] );
send_to_char_bw( spoolbuf, ch );
return;
}
vnum = 0;
buf1 = NULL;
for( pnote = note_list ; pnote ; pnote = pnote->next )
{
if( is_note_to( ch, pnote )
&& ( pnote->spool == spool )
&& ( vnum++ == anum || fAll ) )
{
if( pnote->anon )
{
sprintf( buf, "[{g%3d{x] {cAnonymous{x: %s\n\r%s\n\rTo: %s\n\r",
vnum - 1,
pnote->subject,
pnote->date,
pnote->to_list );
}
else
{
sprintf( buf, "[{g%3d{x] {c%s{x: %s\n\r%s\n\rTo: %s\n\r",
vnum - 1,
pnote->sender,
pnote->subject,
pnote->date,
pnote->to_list );
}
str_cat( &buf1, buf );
str_cat( &buf1, pnote->text );
if ( !fAll )
page_to_char( buf1, ch );
else
str_cat( &buf1, "\n\r" );
ch->last_note[spool] = UMAX( ch->last_note[spool], pnote->date_stamp );
if ( !fAll )
{
free( buf1 );
return;
}
}
}
sprintf( spoolbuf, "No such %s.\n\r", buf2 );
if( !fAll )
send_to_char_bw( spoolbuf, ch );
else
page_to_char( buf1, ch );
free( buf1 );
return;
}
if( !str_cmp( arg, "+" ) )
{
note_attach( ch, spool );
strcpy( buf, ch->pnote->text );
if( strlen( buf ) + strlen( argument ) >= MAX_STRING_LENGTH - 200 )
{
sprintf( spoolbuf, "%s too long.\n\r", buf2 );
spoolbuf[0] = UPPER( spoolbuf[0] );
send_to_char_bw( spoolbuf, ch );
return;
}
strcat( buf, argument );
strcat( buf, "\n\r" );
free_string( ch->pnote->text );
ch->pnote->text = str_dup( buf );
send_to_char_bw( "Ok, line added.\n\r", ch );
return;
}
/*
* 'note help' function add by Ant, Nov '94
*/
if( !str_prefix( arg, "help" ) )
{
do_help( ch, buf2 );
return;
}
/*
* 'note -' function add by Ant, Nov '94
* Updated -Ant, Jan '96
*/
if( !str_cmp( arg, "-" ) )
{
if( !ch->pnote )
{
sprintf( spoolbuf,
"Hmmm....better make a %s before chopping lines from it.\n\r",
buf2 );
send_to_char_bw( spoolbuf, ch );
}
else
{
strcpy( buf, ch->pnote->text );
free_string( ch->pnote->text );
ch->pnote->text = strip_last_line( buf );
send_to_char_bw( "Line Removed.\n\r", ch );
}
return;
}
if( !str_cmp( arg, "anonymous" ) )
{
note_attach( ch, spool );
send_to_char_bw( "Anonymous toggled: ", ch );
if( ch->pnote->anon )
{
ch->pnote->anon = FALSE;
send_to_char_bw( "Off.\n\r", ch );
}
else
{
ch->pnote->anon = TRUE;
send_to_char_bw( "On.\n\r", ch );
}
return;
}
if( !str_prefix( arg, "subject" ) )
{
note_attach( ch, spool );
free_string( ch->pnote->subject );
ch->pnote->subject = str_dup( argument );
send_to_char_bw( "Ok.\n\r", ch );
return;
}
if( !str_prefix( arg, "from" ) && IS_IMMORTAL( ch ) )
{
note_attach( ch, spool );
free_string( ch->pnote->sender );
ch->pnote->sender = str_dup( argument );
send_to_char_bw( "Ok.\n\r", ch );
return;
}
if( !str_prefix( arg, "to" ) )
{
note_attach( ch, spool );
free_string( ch->pnote->to_list );
ch->pnote->to_list = str_dup( argument );
send_to_char_bw( "Ok.\n\r", ch );
return;
}
if( !str_prefix( arg, "clear" ) )
{
if ( ch->pnote )
{
free_string( ch->pnote->text );
free_string( ch->pnote->subject );
free_string( ch->pnote->to_list );
free_string( ch->pnote->date );
free_string( ch->pnote->sender );
ch->pnote->anon = FALSE;
ch->pnote->spool = SPOOL_NOTE;
ch->pnote->next = note_free;
note_free = ch->pnote;
ch->pnote = NULL;
}
send_to_char_bw( "Ok.\n\r", ch );
return;
}
if( !str_prefix( arg, "show" ) )
{
if ( !ch->pnote )
{
sprintf( spoolbuf, "You have no %s in progress.\n\r", buf2 );
send_to_char_bw( spoolbuf, ch );
return;
}
switch( ch->pnote->spool )
{
case( SPOOL_NOTE ):
sprintf( buf2, "note" );
break;
case( SPOOL_IDEA ):
sprintf( buf2, "idea" );
break;
case( SPOOL_MAIL ):
sprintf( buf2, "mail" );
break;
case( SPOOL_BUG ):
sprintf( buf2, "bug" );
break;
case( SPOOL_QUEST ):
sprintf( buf2, "qwest" );
break;
default:
sprintf( buf2, "note" );
break;
}
sprintf( buf, "{c%s{x: %s\n\rTo: %s\n\rSpool: %s\n\r",
ch->pnote->anon ? "Anonymous" : ch->pnote->sender,
ch->pnote->subject,
ch->pnote->to_list,
buf2 );
str_cat( &buf1, buf );
str_cat( &buf1, ch->pnote->text );
page_to_char( buf1, ch );
free( buf1 );
return;
}
if( !str_prefix( arg, "post" ) || !str_prefix( arg, "send" ) )
{
FILE *fp;
char *strtime;
if( ( spool == SPOOL_QUEST ) && !IS_IMMORTAL( ch ) )
{
send_to_char_bw(
"Only Immortals can post to this spool, note deleted.\n\r",
ch );
do_qwest( ch, "clear" );
return;
}
if( !ch->pnote )
{
sprintf( spoolbuf, "You have no %s in progress.\n\r", buf2 );
send_to_char_bw( spoolbuf, ch );
return;
}
if( !str_cmp( ch->pnote->to_list, "" ) )
{
send_to_char_bw(
"You need to provide a recipient (name, all, imm, gods, or imp).\n\r",
ch );
return;
}
if( !str_cmp( ch->pnote->subject, "" ) )
{
send_to_char_bw( "You need to provide a subject.\n\r", ch );
return;
}
ch->pnote->next = NULL;
strtime = ctime( ¤t_time );
strtime[strlen(strtime)-1] = '\0';
free_string( ch->pnote->date );
ch->pnote->date = str_dup( strtime );
ch->pnote->date_stamp = current_time;
if( !note_list )
{
note_list = ch->pnote;
}
else
{
for( pnote = note_list; pnote->next; pnote = pnote->next )
;
pnote->next = ch->pnote;
}
pnote = ch->pnote;
ch->pnote = NULL;
fclose( fpReserve );
if( !( fp = fopen( NOTE_FILE, "a" ) ) )
{
perror( NOTE_FILE );
}
else
{
fprintf( fp, "Sender %s~\n", pnote->sender );
fprintf( fp, "Spool %d\n", pnote->spool );
fprintf( fp, "Anon %d\n", pnote->anon );
fprintf( fp, "Date %s~\n", pnote->date );
fprintf( fp, "Stamp %ld\n", pnote->date_stamp );
fprintf( fp, "To %s~\n", pnote->to_list );
fprintf( fp, "Subject %s~\n", pnote->subject );
fprintf( fp, "Text\n%s~\n\n", pnote->text );
fclose( fp );
}
fpReserve = fopen( NULL_FILE, "r" );
sprintf( spoolbuf, "Your %s has been posted.\n\r", buf2 );
send_to_char_bw( spoolbuf, ch );
return;
}
/*
* Fixed and updated, Jan '96 -Ant
*/
if( !str_prefix( arg, "remove" ) )
{
if( !is_number( argument ) )
{
sprintf( spoolbuf, "%s remove which number?\n\r", buf2 );
spoolbuf[0] = UPPER( spoolbuf[0] );
send_to_char_bw( spoolbuf, ch );
return;
}
anum = atoi( argument );
vnum = 0;
for( pnote = note_list ; pnote ; pnote = pnote->next )
{
if( is_note_to( ch, pnote )
&& ( pnote->spool == spool )
&& ( vnum++ == anum ) )
{
note_remove( ch, pnote, spool );
send_to_char_bw( "Ok.\n\r", ch );
return;
}
}
sprintf( spoolbuf, "No such %s.\n\r", buf2 );
send_to_char_bw( spoolbuf, ch );
return;
}
/*
* Updated, Jan '96 -Ant
*/
if( !str_prefix( arg, "delete" ) && get_trust( ch ) >= 59 )
{
if( !is_number( argument ) )
{
sprintf( spoolbuf, "%s delete which number?\n\r", buf2 );
spoolbuf[0] = UPPER( spoolbuf[0] );
send_to_char_bw( spoolbuf, ch );
return;
}
anum = atoi( argument );
vnum = 0;
for( pnote = note_list ; pnote ; pnote = pnote->next )
{
if( spool == pnote->spool
&& is_note_to( ch, pnote )
&& vnum++ == anum )
{
note_delete( pnote );
send_to_char_bw( "Ok.\n\r", ch );
return;
}
}
sprintf( spoolbuf, "No such %s\n\r", buf2 );
send_to_char_bw( spoolbuf, ch );
return;
}
sprintf( spoolbuf, "Huh? Type 'help %s' for usage.\n\r", buf2 );
send_to_char_bw( spoolbuf, ch );
if( buf1 )
free( buf1 );
return;
}
void note_delete( NOTE_DATA *pnote )
{
FILE *fp;
NOTE_DATA *prev;
/*
* Remove note from linked list.
*/
if ( pnote == note_list )
{
note_list = pnote->next;
}
else
{
for ( prev = note_list ; prev ; prev = prev->next )
{
if ( prev->next == pnote )
break;
}
if ( prev == NULL )
{
bug( "Delete: pnote not found.", 0 );
return;
}
prev->next = pnote->next;
}
free_string( pnote->text );
free_string( pnote->subject );
free_string( pnote->to_list );
free_string( pnote->date );
free_string( pnote->sender );
pnote->spool = SPOOL_NOTE;
pnote->anon = FALSE;
pnote->next = note_free;
note_free = pnote;
/*
* Rewrite entire list.
*/
fclose( fpReserve );
if ( !( fp = fopen( NOTE_FILE, "w" ) ) )
{
perror( NOTE_FILE );
}
else
{
for ( pnote = note_list ; pnote ; pnote = pnote->next )
{
fprintf( fp, "Sender %s~\n", pnote->sender );
fprintf( fp, "Spool %d\n", pnote->spool );
fprintf( fp, "Anon %d\n", pnote->anon );
fprintf( fp, "Date %s~\n", pnote->date );
fprintf( fp, "Stamp %ld\n", pnote->date_stamp );
fprintf( fp, "To %s~\n", pnote->to_list );
fprintf( fp, "Subject %s~\n", pnote->subject );
fprintf( fp, "Text\n%s~\n", pnote->text );
}
fclose( fp );
}
fpReserve = fopen( NULL_FILE, "r" );
return;
}
void do_chat( CHAR_DATA *ch, char *argument )
{
DESCRIPTOR_DATA *d;
char buf[ MAX_STRING_LENGTH ];
bool switched = FALSE;
if( argument[0] == '\0' )
{
if( IS_SET( ch->chan, CHAN_CHAT ) )
{
send_to_char_bw( "Chat channel is now OFF.\n\r", ch );
REMOVE_BIT( ch->chan, CHAN_CHAT );
}
else
{
send_to_char_bw( "Chat channel is now ON.\n\r", ch );
SET_BIT( ch->chan, CHAN_CHAT );
}
}
else
{
if( IS_SET( ch->pen, PEN_NOCHAT ) || IS_SET( ch->pen, PEN_SILENCE ) )
{
send_to_char_bw( "You have been gagged by the administration!\n\r", ch );
return;
}
SET_BIT( ch->chan, CHAN_CHAT );
if( ch->desc
&& ch->desc->original
&& IS_SET( ch->desc->original->act, PLR_SWITCH ) )
{
switched = TRUE;
}
sprintf( buf, "{dYou chat '%s'{x\n\r", argument );
send_to_char( buf, ch );
for( d = descriptor_list ; d ; d = d->next )
{
CHAR_DATA *victim;
victim = d->original ? d->original : d->character;
if( d->connected == CON_PLAYING
&& d->character != ch
&& IS_SET( victim->chan, CHAN_CHAT )
&& !IS_SET( victim->chan, CHAN_QUIET ) )
{
if( switched )
{
act_new( "{y({r$n, switched{y){x",
ch->desc->original, NULL,
victim, TO_VICT, POS_SLEEPING );
}
act_new( "{d$n chats '$t'{x",
ch, argument, victim, TO_VICT, POS_SLEEPING );
}
}
}
}
void do_say( CHAR_DATA *ch, char *argument )
{
if( argument[0] == '\0' )
{
send_to_char_bw( "Say what?\n\r", ch );
return;
}
act_new( "{u$n says '$T'.{x",
ch, NULL, argument, TO_ROOM, POS_RESTING );
act_new( "{uYou say '$T'.{x",
ch, NULL, argument, TO_CHAR, POS_RESTING );
mprog_speech_trigger( argument, ch );
return;
}
void do_shout( CHAR_DATA *ch, char *argument )
{
/* TODO */
return;
}
void do_immtalk( CHAR_DATA *ch, char *argument )
{
DESCRIPTOR_DATA *d;
char buf[ MAX_STRING_LENGTH ];
bool switched = FALSE;
if( argument[0] == '\0' )
{
if( IS_SET( ch->chan, CHAN_IMM ) )
{
send_to_char_bw( "Immortal channel is now OFF.\n\r", ch );
REMOVE_BIT( ch->chan, CHAN_IMM );
}
else
{
send_to_char_bw( "Immortal channel is now ON.\n\r", ch );
SET_BIT( ch->chan, CHAN_IMM );
}
}
else
{
if( IS_SET( ch->pen, PEN_SILENCE ) )
{
send_to_char_bw( "You have been gagged by the administration!\n\r", ch );
return;
}
SET_BIT( ch->chan, CHAN_IMM );
if( ch->desc
&& ch->desc->original
&& IS_SET( ch->desc->original->act, PLR_SWITCH ) )
{
switched = TRUE;
}
sprintf( buf, "$n: %s", argument );
act_new( "{i$n [{IImmortal{i]: $t{x",
ch, argument, NULL, TO_CHAR, POS_DEAD );
for( d = descriptor_list ; d ; d = d->next )
{
CHAR_DATA *victim;
victim = d->original ? d->original : d->character;
if( d->connected <= CON_PLAYING
&& d->character != ch
&& IS_SET( victim->chan, CHAN_IMM )
&& victim->wizbit )
{
if( switched )
{
act_new( "{y({r$n, switched{y){x",
ch->desc->original, NULL,
victim, TO_VICT, POS_DEAD );
}
act_new("{i$n [{IImmortal{i]: $t{x",
ch, argument, victim, TO_VICT, POS_DEAD );
}
}
}
}
void do_tell( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
char arg[ MAX_INPUT_LENGTH ];
if( !IS_NPC( ch ) && IS_SET( ch->pen, PEN_SILENCE ) )
{
send_to_char_bw( "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_bw( "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 ) )
|| ( IS_NPC( victim ) && victim->in_room != ch->in_room ) )
{
send_to_char_bw( "They aren't here.\n\r", ch );
return;
}
act_new( "{kYou tell $N '$t'.{x",
ch, argument, victim, TO_CHAR, POS_SLEEPING );
act_new( "{k$n tells you '$t'.{x",
ch, argument, victim, TO_VICT, POS_SLEEPING );
victim->reply = ch;
return;
}
void do_reply( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
if( !IS_NPC( ch ) && IS_SET( ch->pen, PEN_SILENCE ) )
{
send_to_char_bw( "Your message didn't get through.\n\r", ch );
return;
}
if( !( victim = ch->reply ) )
{
send_to_char_bw( "They aren't here.\n\r", ch );
return;
}
if( !IS_IMMORTAL( ch ) && !IS_AWAKE( victim ) )
{
act_new( "$E can't hear you.",
ch, 0, victim, TO_CHAR, POS_SLEEPING );
return;
}
act_new( "{lYou tell $N '$t'.{x",
ch, argument, victim, TO_CHAR, POS_SLEEPING );
act_new( "{l$n tells you '$t'.{x",
ch, argument, victim, TO_VICT, POS_SLEEPING );
victim->reply = ch;
return;
}
void do_emote( CHAR_DATA *ch, char *argument )
{
char *plast;
char buf[ MAX_STRING_LENGTH ];
if( !IS_NPC( ch ) && IS_SET( ch->act, PEN_NOEMOTE ) )
{
send_to_char_bw( "You can't show your emotions.\n\r", ch );
return;
}
if( argument[0] == '\0' )
{
send_to_char_bw( "Emote what?\n\r", ch );
return;
}
for( plast = argument ; *plast != '\0' ; plast++ )
;
strcpy( buf, argument );
if( isalpha( plast[-1] ) )
strcat( buf, "." );
act_new( "$n $T", ch, NULL, buf, TO_ROOM, POS_RESTING );
act_new( "$n $T", ch, NULL, buf, TO_CHAR, POS_RESTING );
return;
}
void do_pose( CHAR_DATA *ch, char *argument )
{
send_to_char_bw( "Pose removed for re-coding.\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_rent( CHAR_DATA *ch, char *argument )
{
send_to_char_bw( "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_bw( "No way! You are fighting.\n\r", ch );
return;
}
if( ch->position < POS_STUNNED )
{
send_to_char_bw( "You're not DEAD yet.\n\r", ch );
return;
}
send_to_char(
"Where I traveled I came forth, from the earth, into the weave, and out to space again.\n\r",
ch );
act_new( "$n has left the game.",
ch, NULL, NULL, TO_ROOM, POS_RESTING );
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 )
close_socket( d );
return;
}
void do_save( CHAR_DATA *ch, char *argument )
{
if( IS_NPC( ch ) )
return;
save_char_obj( ch );
send_to_char_bw( "Ok.\n\r", ch );
return;
}
void do_follow( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
char arg[ MAX_INPUT_LENGTH ];
one_argument( argument, arg );
if( arg[ 0 ] == '\0' )
{
send_to_char_bw( "Follow whom?\n\r", ch );
return;
}
if( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char_bw( "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_bw( "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 != 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 arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
CHAR_DATA *och;
CHAR_DATA *och_next;
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 ) ) == 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 = ch->in_room->people; och != NULL; och = och_next )
{
och_next = och->next_in_room;
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, FALSE );
}
}
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_DATA *victim;
char buf[ MAX_STRING_LENGTH ];
char arg[ MAX_INPUT_LENGTH ];
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 ; gch = gch->next )
{
if( is_same_group( gch, ch ) )
{
sprintf( buf,
"[%s] %-16s %4d/%4d hp %4d/%4d mana %4d/%4d mv %5d xp\n\r",
IS_NPC( gch ) ? "Mob " : gch->class->who_name,
capitalize( 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 ) ) )
{
send_to_char( "They aren't here.\n\r", ch );
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( "$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;
}
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;
}
/*
* 'Split' originally by Gnort, God of Chaos.
*/
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 = ch->in_room->people; gch != NULL; 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, "$n splits %d gold coins. Your share is %d gold coins.",
amount, share );
for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room )
{
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, 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->pen, PEN_NOTELL ) )
{
send_to_char( "Your message didn't get through!\n\r", ch );
return;
}
/*
* Note use of send_to_char, so gtell works on sleepers.
*/
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 != NULL ) ach = ach->leader;
if ( bch->leader != NULL ) bch = bch->leader;
return ach == bch;
}
/*
* Colour setting and unsetting, way cool, Ant Oct 94
* revised to include config colour, Ant Feb 95
*/
void do_colour( CHAR_DATA *ch, char *argument )
{
char arg[ MAX_STRING_LENGTH ];
if( IS_NPC( ch ) )
return;
argument = one_argument( argument, arg );
if( !*arg )
{
if( !IS_SET( ch->act, PLR_COLOUR ) )
{
send_to_char_bw( "Colour is now ON, Way Cool!\n\r", ch );
SET_BIT( ch->act, PLR_COLOUR );
}
else
{
send_to_char_bw( "Colour is now OFF, <sigh>\n\r", ch );
REMOVE_BIT( ch->act, PLR_COLOUR );
}
return;
}
if( !str_cmp( arg, "default" ) )
{
default_colour( ch );
send_to_char_bw( "Colour setting set to default values.\n\r", ch );
return;
}
if( !str_cmp( arg, "all" ) )
{
all_colour( ch, argument );
return;
}
if( !str_cmp( arg, "text" ) )
{
ALTER_COLOUR( text )
}
else if( !str_cmp( arg, "auction" ) )
{
ALTER_COLOUR( auction )
}
else if( !str_cmp( arg, "chat" ) )
{
ALTER_COLOUR( chat )
}
else if( !str_cmp( arg, "music" ) )
{
ALTER_COLOUR( music )
}
else if( !str_cmp( arg, "question" ) )
{
ALTER_COLOUR( question )
}
else if( !str_cmp( arg, "answer" ) )
{
ALTER_COLOUR( answer )
}
else if( !str_cmp( arg, "class_text" ) )
{
ALTER_COLOUR( class_text )
}
else if( !str_cmp( arg, "class_name" ) )
{
ALTER_COLOUR( class_name )
}
else if( !str_cmp( arg, "immtalk_text" ) )
{
ALTER_COLOUR( immtalk_text )
}
else if( !str_cmp( arg, "immtalk_type" ) )
{
ALTER_COLOUR( immtalk_type )
}
else if( !str_cmp( arg, "info" ) )
{
ALTER_COLOUR( info )
}
else if( !str_cmp( arg, "tell" ) )
{
ALTER_COLOUR( tell )
}
else if( !str_cmp( arg, "reply" ) )
{
ALTER_COLOUR( reply )
}
else if( !str_cmp( arg, "say" ) )
{
ALTER_COLOUR( say )
}
else if( !str_cmp( arg, "gtell_text" ) )
{
ALTER_COLOUR( gtell_text )
}
else if( !str_cmp( arg, "gtell_type" ) )
{
ALTER_COLOUR( gtell_type )
}
else if( !str_cmp( arg, "bbro" ) )
{
ALTER_COLOUR( bbro )
}
else if( !str_cmp( arg, "room_title" ) )
{
ALTER_COLOUR( room_title )
}
else if( !str_cmp( arg, "room_text" ) )
{
ALTER_COLOUR( room_text )
}
else if( !str_cmp( arg, "room_exits" ) )
{
ALTER_COLOUR( room_exits )
}
else if( !str_cmp( arg, "room_things" ) )
{
ALTER_COLOUR( room_things )
}
else if( !str_cmp( arg, "prompt" ) )
{
ALTER_COLOUR( prompt )
}
else if( !str_cmp( arg, "fight_death" ) )
{
ALTER_COLOUR( fight_death )
}
else if( !str_cmp( arg, "fight_yhit" ) )
{
ALTER_COLOUR( fight_yhit )
}
else if( !str_cmp( arg, "fight_ohit" ) )
{
ALTER_COLOUR( fight_ohit )
}
else if( !str_cmp( arg, "fight_thit" ) )
{
ALTER_COLOUR( fight_thit )
}
else if( !str_cmp( arg, "fight_skill" ) )
{
ALTER_COLOUR( fight_skill )
}
else
{
send_to_char_bw( "Unrecognised Colour Parameter Not Set.\n\r", ch );
return;
}
send_to_char_bw( "New Colour Parameter Set.\n\r", ch );
return;
}
void do_unread( CHAR_DATA *ch, char *argument )
{
NOTE_DATA *pnote;
char sbuf[ MAX_STRING_LENGTH ];
char buf[ MAX_STRING_LENGTH ];
int notes = 0;
int spool = 0;
for( spool = 0 ; spool < MAX_SPOOL ; spool++ )
{
notes = 0;
switch( spool )
{
case( SPOOL_NOTE ):
sprintf( sbuf, "note" );
break;
case( SPOOL_IDEA ):
sprintf( sbuf, "idea" );
break;
case( SPOOL_MAIL ):
sprintf( sbuf, "mail" );
break;
case( SPOOL_BUG ):
sprintf( sbuf, "bug" );
break;
case( SPOOL_QUEST ):
sprintf( sbuf, "qwest" );
break;
default:
sprintf( sbuf, "note" );
break;
}
for( pnote = note_list ; pnote ; pnote = pnote->next )
{
if( is_note_to( ch, pnote )
&& str_cmp( ch->name, pnote->sender )
&& pnote->spool == spool
&& pnote->date_stamp > ch->last_note[ spool ] )
notes++;
}
if( notes == 1 )
{
sprintf( buf, "\n\rYou have one new %s waiting.\n\r", sbuf );
send_to_char_bw( buf, ch );
}
else if( notes > 1 )
{
sprintf( buf, "\n\rYou have %d new %ss waiting.\n\r",
notes,
sbuf );
send_to_char_bw( buf, ch );
}
}
return;
}