/*
....[@@@..[@@@..............[@.................. MUD++ is a written from
....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and
....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++.
....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing
....[@......[@..[@@@@@..[@@@@@.................. development project. All
................................................ contributions are welcome.
....Copyright(C).1995.Melvin.Smith.............. Enjoy.
------------------------------------------------------------------------------
Melvin Smith (aka Fusion) msmith@falcon.mercer.peachnet.edu
MUD++ development mailing list mudpp-list@spice.com
------------------------------------------------------------------------------
pc_wiz.cc
*/
#include "string.h"
#include "llist.h"
#include "room.h"
#include "repop.h"
#include "indexable.h"
#include "server.h"
#include "area.h"
#include "bit.h"
#include "screen.h"
#include "pc.h"
#include "global.h"
// This is a utility function which I change often just for debuggin
// things
void PC::do_debug( String & )
{
int i;
String strOut;
char buf[ 4096 ];
char buf2[ 4096 ];
String str( 4096 );
static timeval avg;
timeval tin1, tout1, dif1;
timeval tin2, tout2, dif2, dif3;
strcpy( buf2, "testing dfasdfkjsadhfklasdfhasdlkfsdfkljh" );
gettimeofday( &tin1, 0 );
for( i = 0; i < 100000; i++ )
{
strcpy( buf, buf2 );
}
gettimeofday( &tout1, 0 );
dif1.tv_sec = tout1.tv_sec - tin1.tv_sec;
dif1.tv_usec = tout1.tv_usec - tin1.tv_usec;
if( dif1.tv_usec < 0 )
{
dif1.tv_sec--;
dif1.tv_usec += 1000000;
}
strOut.sprintf( "char time: secs(%ld) usec(%ld)\n\r",
dif1.tv_sec, dif1.tv_usec );
out( strOut );
gettimeofday( &tin2, 0 );
for( i = 0; i < 100000; i++ )
{
str = buf2;
}
gettimeofday( &tout2, 0 );
dif2.tv_sec = tout2.tv_sec - tin2.tv_sec;
dif2.tv_usec = tout2.tv_usec - tin2.tv_usec;
if( dif2.tv_usec < 0 )
{
dif2.tv_sec--;
dif2.tv_usec += 1000000;
}
strOut.sprintf( "Str time: secs(%ld) usec(%ld)\n\r",
dif2.tv_sec, dif2.tv_usec );
out( strOut );
dif3.tv_sec = dif2.tv_sec - dif1.tv_sec;
dif3.tv_usec = dif2.tv_usec - dif1.tv_usec;
if( dif3.tv_usec < 0 )
{
dif3.tv_sec--;
dif3.tv_usec += 1000000;
}
strOut.sprintf( "Diff: secs(%ld) usec(%ld)\n\r",
dif3.tv_sec, dif3.tv_usec );
out( strOut );
}
// Just a test to get ident working. Will do non-blocking when
// this is done.
void PC::do_ident( String & arg )
{
char ip[ 256 ];
char buf[ 256 ];
PC *pc;
Socket *socket;
if( !( pc = getPCWorld( arg ) ) )
{
out( "No such player connected.\n\r" );
return;
}
strcpy( ip, pc->getSock()->getHostName() );
socket = new Socket( ip, 113 );
if( socket->error() )
{
out( "Socket error.\n\r" );
delete socket;
return;
}
if( socket->connect() == -1 )
{
out( "Connect error.\n\r" );
delete socket;
return;
}
out( "Connected to ident server on " );
out( socket->getHostName() );
out( "\n\r" );
int foreign_port = pc->getSock()->getPort();
int size = sprintf( buf, "%d , %d\n\r", foreign_port, 4000 );
socket->write( buf, size );
*buf = 0;
while( !*buf )
socket->read( buf );
delete socket;
out( buf );
}
void PC::do_cat( String & arg )
{
if( !arg )
return;
view( arg.chars() );
}
void PC::do_users( String & )
{
String str;
PC *pc;
LList<PC> tlist = pcs;
tlist.reset();
str = "Name Host Foreign Port\n\r";
while( ( pc = tlist.peek() ) )
{
tlist.next();
str.sprintfAdd( "%13s%20s%-7d\n\r", pc->getName().chars(),
pc->getSock()->getHostName(),
pc->getSock()->getPort() );
}
out( str );
}
void PC::do_echo( String & arg )
{
String str;
str << "\n\n\r" << arg << "\n\r";
outAllCharExcept( str, 0, 0 );
}
void PC::do_immtalk( String & arg )
{
PC *ch;
LList<PC> tlist = pcs;
String str;
str << BYELLOW << name << " : " << arg << "\n\r" << NTEXT;
tlist.reset();
while( ( ch = tlist.peek() ) )
{
if( ch != this )
ch->out( "\n\r" );
ch->out( str );
tlist.next();
}
}
void PC::do_advance ( String & arg )
{
if( classnow != CLASS_IMM )
{
out("You wish you were this powerful.\n\r");
return;
}
arg.startArgs();
String argName = arg.getArg();
String argLevel = arg.getArg();
if( !argName || !argLevel )
{
out( "Usage: advance <person> <level>\n\r" );
return;
}
PC *plr = in_room->getPC( argName );
if( !plr )
{
out( "No one here by that name.\n\r" );
return;
}
int lev = argLevel.asInt();
if( lev < 1 )
{
out( "No can do.\n\r" );
return;
}
// Need to check levels here.
plr->advance( lev );
}
void PC::do_memory( String & )
{
out( "\n\r[disabled for now --Fusion]\n\r" );
}
void PC::do_invis( String & )
{
char buf[ BUF ];
/*if( IsInvisible() )
{
out( "You fade into existence.\n\r" );
sprintf( buf, "\n\n\r%s fades into existence.\n\r", name.chars() );
}
else
{
out( "You suddenly vanish.\n\r" );
sprintf( buf, "\n\n\r%s suddenly vanishes into thin air.\n\r", name.chars() );
}
*/
//TOGGLE_BIT( obj_flags, OBJ_INVISIBLE );
// in_room->outAllCharExcept( buf, this, NULL );
}
void PC::do_goto( String & arg )
{
String str;
Char *ch;
Room *to;
// Search players first, then NPCs
if( !( ch = getPCWorld( arg ) ) )
ch = getNPCWorld( arg );
if( ch && ch->inRoom() )
to = ch->inRoom();
else
{
// Now try rooms in this area unless scope: was specified
Index x( arg );
if( !x.getScope() )
x.setScope( in_room->getArea()->getKey() );
if( !( to = lookupRoom( x ) ) )
{
// Now try global (no scope)
x.setScope( "" );
to = lookupRoom( x );
}
}
if( !to )
{
out("No such location.\n\r");
return;
}
if( to == in_room )
return;
str << "\n\r" << name << " disappears in a puff of smoke.\n\r";
in_room->outAllCharExcept( str, this, NULL );
// We can use simple out() since character not in room yet.
in_room->rmCharInv( this );
str.clr();
str << "\n\r" << name << " appears with an ear-splitting BANG!!\n\r";
to->out( str );
to->addCharInv( this );
do_look( "" );
}
void PC::do_transfer( String & arg )
{
Room *src;
Room *dest = in_room;
Char *ch = getPCWorld( arg );
if( !ch )
{
ch = getNPCWorld( arg );
if( !ch )
{
out( "No such character, Coolio.\n\r" );
return;
}
}
if( !( src = ch->inRoom() ) )
{
out( "PC::do_transfer() : victim not in a room." );
return;
}
src->outAllCharExcept( ch->getShort(), ch, 0 );
src->outAllCharExcept( " dissappears in a mushroom cloud.\n\r", ch, 0 );
ch->inRoom()->rmCharInv( ch );
ch->out( shortdesc );
ch->out( " has transferred you!\n\r" );
dest->outAllCharExcept( ch->getShort(), ch, 0 );
dest->outAllCharExcept( " arrives from a puff of smoke.\n\r", ch, 0 );
dest->addCharInv( ch );
if( ch->isPC() )
((PC *)ch)->do_look( "" );
}
void PC::do_slay( String & arg )
{
if( !arg )
{
out( "\n\rWho shall we be slaying?\n\r" );
return;
}
Char *ch = in_room->getChar( arg );
if( !ch )
{
out( "\n\rHmm, you must need your eyes checked.\n\r" );
return;
}
if( ch == this )
{
out( "\n\rAren't we funny today?\n\r" );
return;
}
// OK - Lets build the corpse Object.
// This stuff is so straighforward I don't make a seperate function.
String str;
Object *corpse = new Object;
corpse->setName( "corpse" );
str << "the corpse of " << ch->getShort();
corpse->setShort( str );
str.clr();
str << "The corpse of " << ch->getShort() << " lies here, rotting.";
corpse->setLong( str );
corpse->setWeight( ch->getWeight() );
corpse->setType( ITEM_CORPSE );
corpse->setTimer( 2 );
corpse->toWorld();
in_room->addObjInv( corpse );
ch->inRoom()->rmCharInv( ch );
ch->out( "\n\n\r** YOU HAVE BEEN SLAIN!!! **\n\r" );
out( "\n\rAAAAAHG - Blood everywhere!!!\n\r" );
str.clr();
str << "\n\n\r" << name << " chops " << ch->getShort()
<< " to pieces!!!\n\r*SPLATTER*\n\r";
in_room->outAllCharExcept( str, this, ch );
// Mob corpses are traditional. Transfer the inventory to corpse.
if( ch->isNPC() )
{
}
if( ch->isNPC() )
{
ch->fromWorld();
delete ch;
return;
}
//INCOMPLETE
((PC*)ch)->setState( STATE_MAIN_MENU );
}
void PC::do_purge( String & )
{
Char *ch;
Object *obj;
in_room->chars.reset();
while( ( ch = in_room->chars.peek() ) )
{
if( ch->isNPC() )
{
out( "Purging " );
out( ch->getShort() );
out( ".\n\r" );
in_room->rmCharInv( ch );
ch->fromWorld();
delete ch;
continue;
}
in_room->chars.next();
}
in_room->inv.reset();
while( ( obj = in_room->inv.remove() ) )
{
out( "Purging " );
out( obj->getShort() );
out( ".\n\r" );
obj->fromWorld();
delete obj;
}
}
void PC::do_page( String & )
{
}
void PC::do_reboot( String & )
{
String str;
DOWN = 1;
REBOOT = 1;
str << "\n\rRebooted by " << name << "\n\n\r";
out( str );
}
void PC::do_shutdown( String & )
{
String str;
DOWN = 1;
str << "\n\rShutdown by " << name << "\n\n\r";
out( str );
}
void PC::do_rfind( String & arg )
{
bool global = false;
// bool wildcard = false;
String str( BUF * 2 );
const Room * ptr;
Area *area = in_room->getArea();
if( arg == "all" )
{
global = true;
areas.reset();
while( ( area = areas.peek() ) )
{
areas.next();
str << "\n\r--:" << area->getName() << ":--\n\r";
area->roomIndex.reset();
while( ( ptr = area->roomIndex.peek() ) )
{
area->roomIndex.next();
str.sprintfAdd( "%-30s%-40s\n\r",
ptr->getKey().chars(),
ptr->getName().chars() );
}
}
}
else
{
str << "Rooms in this area:\n\r-----------------------\n\r";
area->roomIndex.reset();
while( ( ptr = area->roomIndex.peek() ) )
{
area->roomIndex.next();
str.sprintfAdd( "%-30s%-40s\n\r",
ptr->getKey().chars(),
ptr->getName().chars() );
}
}
out( str );
}
void PC::do_ofind( String & arg )
{
String str( BUF * 2 );
String strName;
String strArea;
bool wildcard = false;
const Object * ptr;
Area *area;
bool global = false;
if( !arg )
{
out( "Find what?\n\r" );
return;
}
// Use index object to parse arg
Index index( arg );
strName = index.getKey();
strArea = index.getScope();
IndexList<Object> *objIndex;
if( strArea && strArea == "*" )
{
global = true;
}
if( strName == "*" )
{
wildcard = true;
}
str << "Looking up [" << strName << "]\n\r-------------\n\r";
if( !global )
{
if( !strArea )
objIndex = &in_room->getArea()->objIndex;
else
{
if( !( area = lookupArea( strArea ) ) )
{
str << "Unknown area " << strArea << "\n\r";
out( str );
return;
}
objIndex = &area->objIndex;
}
objIndex->reset();
while( ( ptr = objIndex->peek() ) )
{
index = objIndex->getIndex();
objIndex->next();
if( !wildcard && !ptr->isName( strName ) )
continue;
str.sprintfAdd( "%-30s%-40s\n\r",
index.getKey().chars(),
ptr->getShort().chars() );
}
}
else
{
areas.reset();
while( ( area = areas.peek() ) )
{
areas.next();
objIndex = &area->objIndex;
objIndex->reset();
while( ( ptr = objIndex->peek() ) )
{
// Get the index of that object
index = objIndex->getIndex();
// Then increment
objIndex->next();
if( !wildcard && !ptr->isName( strName ) )
continue;
str.sprintfAdd( "%17s:%-30s%-31s\n\r",
area->getKey().chars(),
index.getKey().chars(),
ptr->getShort().chars() );
}
}
}
out( str );
}
void PC::do_owhere( String & arg )
{
Object *obj;
String str( BUF );
if( !arg )
return;
objects.reset();
while( ( obj = objects.peek() ) )
{
objects.next();
if( !obj->isName( arg ) )
continue;
else if( obj->inRoom() )
{
str.sprintfAdd( "%-20s in room %20s\n",
obj->getShort().chars(), obj->inRoom()->getName().chars() );
}
else if( obj->inChar() )
{
str.sprintfAdd( "%-20s carried by %20s\n",
obj->getShort().chars(), obj->inChar()->getShort().chars() );
}
else if( obj->inObj() )
{
str.sprintfAdd( "%-20s inside %20s\n",
obj->getShort().chars(), obj->inObj()->getShort().chars() );
}
else
{
str.sprintfAdd( "%-20s is just sort of floating around! BUG!\n",
obj->getShort().chars() );
}
}
if( !str )
str.sprintf( "Could not find any %s.\n\r", arg.chars() );
out( str );
}
void PC::do_mfind( String & arg )
{
String str( BUF * 2 );
String strName;
String strArea;
char arg1[ 256 ];
const NPC *ptr;
Area *area;
bool global = false;
bool wildcard = false;
if( !arg )
{
out( "Find what?\n\r" );
return;
}
IndexList<NPC> *npcIndex;
// Use index constructor to parse the string
Index index( arg );
strArea = index.getScope();
strName = index.getKey();
if( strArea && strArea == "*" )
{
global = true;
}
if( strName == "*" )
{
wildcard = true;
}
str << "Looking up [" << strName << "]\n\r-------------\n\r";
if( !global )
{
if( !strArea )
npcIndex = &in_room->getArea()->npcIndex;
else
{
if( !( area = lookupArea( strArea ) ) )
{
str << "Unknown area " << strArea << "\n\r";
out( str );
return;
}
npcIndex = &area->npcIndex;
}
npcIndex->reset();
while( ( ptr = npcIndex->peek() ) )
{
// Get index for that npc
index = npcIndex->getIndex();
// Increment
npcIndex->next();
if( !wildcard && !ptr->isName( strName ) )
continue;
str.sprintfAdd( "%-30s%-40s\n\r",
index.getKey().chars(),
ptr->getShort().chars() );
}
}
else
{
areas.reset();
while( ( area = areas.peek() ) )
{
areas.next();
npcIndex = &area->npcIndex;
npcIndex->reset();
while( ( ptr = npcIndex->peek() ) )
{
// Get index of npc
index = npcIndex->getIndex();
// Then increment
npcIndex->next();
if( !wildcard && !ptr->isName( strName ) )
continue;
str.sprintfAdd( "%17s:%-25s%-31s\n\r",
area->getKey().chars(),
index.getKey().chars(),
ptr->getShort().chars() );
}
}
}
out( str );
}
void PC::do_cset( String & arg )
{
}
void PC::do_grant( String & arg )
{
PC *ch;
String person;
String privilege;
int bit;
arg.startArgs();
privilege = arg.getArg();
person = arg.getArg();
if( !person || !privilege )
{
out( "grant <privilege> <person>\n\r" );
return;
}
ch = getPCWorld( person );
if( !ch )
{
out( "Could not find anyone by that name.\n\r" );
return;
}
if( privilege == "all" )
{
}
else
{
bit = getPrivBit( privilege.chars() );
if( bit == NULLBIT )
{
out( "No such privilege to grant.\n\r" );
return;
}
ch->setPrivBit( bit );
out( "Privilege granted to " );
out( ch->getName() );
out( ".\n\r" );
}
}
void PC::do_revoke( String & arg )
{
PC *ch;
int bit;
String privilege;
String person;
arg.startArgs();
privilege = arg.getArg();
person = arg.getArg();
if( !person || !privilege )
{
out( "revoke <privilege> <person>\n\r" );
return;
}
ch = getPCWorld( person );
if( !ch )
{
out( "Could not find anyone by that name.\n\r" );
return;
}
if( privilege == "all" )
{
}
else
{
bit = getPrivBit( privilege.chars() );
if( bit == NULLBIT )
{
out( "No such privilege to revoke.\n\r" );
return;
}
ch->rmPrivBit( bit );
out( "Privilege revoked from " );
out( ch->getName() );
out( ".\n\r" );
}
}