/****************************************************************************
* Online Building and Editing Module *
*****************************************************************************/
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "merc.h"
extern int top_ed;
EXTRA_DESCR_DATA *SetRExtra( ROOM_INDEX_DATA *room, char *keywords )
{
EXTRA_DESCR_DATA *ed;
for ( ed = room->first_extradesc; ed; ed = ed->next )
{
if ( is_name( keywords, ed->keyword ) )
break;
}
if ( !ed )
{
CREATE( ed, EXTRA_DESCR_DATA, 1 );
LINK( ed, room->first_extradesc, room->last_extradesc, next, prev
);
ed->keyword = STRALLOC( keywords );
ed->description = STRALLOC( "" );
top_ed++;
}
return ed;
}
bool DelRExtra( ROOM_INDEX_DATA *room, char *keywords )
{
EXTRA_DESCR_DATA *rmed;
for ( rmed = room->first_extradesc; rmed; rmed = rmed->next )
{
if ( is_name( keywords, rmed->keyword ) )
break;
}
if ( !rmed )
return FALSE;
UNLINK( rmed, room->first_extradesc, room->last_extradesc, next, prev
);
STRFREE( rmed->keyword );
STRFREE( rmed->description );
DISPOSE( rmed );
top_ed--;
return TRUE;
}
EXTRA_DESCR_DATA *SetOExtra( OBJ_DATA *obj, char *keywords )
{
EXTRA_DESCR_DATA *ed;
for ( ed = obj->first_extradesc; ed; ed = ed->next )
{
if ( is_name( keywords, ed->keyword ) )
break;
}
if ( !ed )
{
CREATE( ed, EXTRA_DESCR_DATA, 1 );
LINK( ed, obj->first_extradesc, obj->last_extradesc, next, prev );
ed->keyword = STRALLOC( keywords );
ed->description = STRALLOC( "" );
top_ed++;
}
return ed;
}
bool DelOExtra( OBJ_DATA *obj, char *keywords )
{
EXTRA_DESCR_DATA *rmed;
for ( rmed = obj->first_extradesc; rmed; rmed = rmed->next )
{
if ( is_name( keywords, rmed->keyword ) )
break;
}
if ( !rmed )
return FALSE;
UNLINK( rmed, obj->first_extradesc, obj->last_extradesc, next, prev );
STRFREE( rmed->keyword );
STRFREE( rmed->description );
DISPOSE( rmed );
top_ed--;
return TRUE;
}
EXTRA_DESCR_DATA *SetOExtraProto( OBJ_INDEX_DATA *obj, char *keywords )
{
EXTRA_DESCR_DATA *ed;
for ( ed = obj->first_extradesc; ed; ed = ed->next )
{
if ( is_name( keywords, ed->keyword ) )
break;
}
if ( !ed )
{
CREATE( ed, EXTRA_DESCR_DATA, 1 );
LINK( ed, obj->first_extradesc, obj->last_extradesc, next, prev );
ed->keyword = STRALLOC( keywords );
ed->description = STRALLOC( "" );
top_ed++;
}
return ed;
}
bool DelOExtraProto( OBJ_INDEX_DATA *obj, char *keywords )
{
EXTRA_DESCR_DATA *rmed;
for ( rmed = obj->first_extradesc; rmed; rmed = rmed->next )
{
if ( is_name( keywords, rmed->keyword ) )
break;
}
if ( !rmed )
return FALSE;
UNLINK( rmed, obj->first_extradesc, obj->last_extradesc, next, prev );
STRFREE( rmed->keyword );
STRFREE( rmed->description );
DISPOSE( rmed );
top_ed--;
return TRUE;
}
/*
* Function to get the equivelant exit of DIR 0-MAXDIR out of linked list.
* Made to allow old-style diku-merc exit functions to work. -Thoric
*/
EXIT_DATA *get_exit( ROOM_INDEX_DATA *room, sh_int dir )
{
EXIT_DATA *xit;
if ( !room )
{
bug( "Get_exit: NULL room", 0 );
return NULL;
}
for (xit = room->first_exit; xit; xit = xit->next )
if ( xit->vdir == dir )
return xit;
return NULL;
}
/*
* Function to get an exit, leading the the specified room
*/
EXIT_DATA *get_exit_to( ROOM_INDEX_DATA *room, sh_int dir, int vnum )
{
EXIT_DATA *xit;
if ( !room )
{
bug( "Get_exit: NULL room", 0 );
return NULL;
}
for (xit = room->first_exit; xit; xit = xit->next )
if ( xit->vdir == dir && xit->vnum == vnum )
return xit;
return NULL;
}
/*
* Function to get the nth exit of a room -Thoric
*/
EXIT_DATA *get_exit_num( ROOM_INDEX_DATA *room, sh_int count )
{
EXIT_DATA *xit;
int cnt;
if ( !room )
{
bug( "Get_exit: NULL room", 0 );
return NULL;
}
for (cnt = 0, xit = room->first_exit; xit; xit = xit->next )
if ( ++cnt == count )
return xit;
return NULL;
}
/*
* Returns value 0 - 9 based on directional text.
*/
int get_dir( char *txt )
{
int edir;
char c1,c2;
c1 = txt[0];
if ( c1 == '\0' )
return 0;
c2 = txt[1];
edir = 0;
switch ( c1 )
{
case 'n':
switch ( c2 )
{
default: edir = 0; break; /* north */
}
break; case '0': edir = 0; break; /* north */
case 'e': case '1': edir = 1; break; /* east */
case 's':
switch ( c2 )
{
default: edir = 2; break; /* south */
}
break; case '2': edir = 2; break; /* south */
case 'w': case '3': edir = 3; break; /* west */
case 'u': case '4': edir = 4; break; /* up */
case 'd': case '5': edir = 5; break; /* down */
}
return edir;
}
char * const ex_flags [] =
{
"isdoor", "closed", "locked", "pickproof"
};
char * const r_flags [] =
{
"dark", "no_otrans",
"nomob", "indoors",
"private", "safe",
"solitary", "petshop",
"norecall", "noteleport",
"totaldarkness",
"blade_barrier", "arena",
"flaming", "silence"
};
char * const o_flags [] =
{
"glow", "hum", "thrown",
"keep", "vanish",
"invis", "magic",
"nodrop", "bless",
"antigood", "antievil",
"antineutral", "noremove",
"inventory", "loyal",
"shadowplane"
};
char * const w_flags [] =
{
"take", "finger", "neck", "body", "head", "legs", "feet", "hands", "arms",
"shield", "about", "waist", "wrist", "wield", "hold", "face"
};
char * const o_types [] =
{
"none", "light", "scroll", "wand", "staff", "weapon",
"treasure", "armor", "potion", "furniture", "trash", "container",
"drinkcon", "key", "food", "money", "boat",
"corpse", "corpse_pc", "fountain", "pill",
"portal", "egg",
"voodoo", "stake",
"missile", "ammo",
"quest", "questcard",
"symbol", "book",
"page", "tool",
"wall", "copper",
"iron", "steel",
"adamantite", "gemstone",
"hilt"
};
char * const a_types [] =
{
"none", "strength", "dexterity", "intelligence", "wisdom", "constitution",
"sex", "class", "level", "age", "height", "weight", "mana", "hit", "move",
"gold", "experience", "armor", "hitroll", "damroll", "save_para",
"save_rod","save_petri",
"save_breath",
"save_spell",
"poly"
};
char * const a_flags [] =
{
"blind", "invisible", "detect_evil", "detect_invis", "detect_magic",
"detect_hidden", "shadowplane", "sanctuary", "faerie_fire", "infrared",
"curse",
"flaming", "poison", "protect", "ethereal", "sneak", "hide", "sleep",
"charm", "flying", "pass_door", "polymorph", "shadowsight", "webbed",
"tendrils", "drowfire", "zuloform", "shift", "peace", "infirmity",
"godbless", "satansbless", "totalblind",
"steelshield", "monkflaming" };
char * const act_flags [] =
{
"npc", "sentinel", "scavenger", "aggressive", "stayarea", "wimpy", "pet",
"train", "practice", "mount", "noparts", "noexp", "prototype", "r1" };
char * const plr_flags [] =
{
"npc", "autoexit", "autoloot", "autosac", "blank", "brief", "combine",
"prompt", "telnet_ga", "holylight", "wizinvis", "ansi", "silence",
"vt102", "incog", "notell", "log", "deny", "freeze", "godless",
"watcher", "acid", "challenger","challendged",
"r1", "r2"
};
char * const wear_locs [] =
{
"light", "finger1", "finger2", "neck1", "neck2", "body", "head", "legs",
"feet", "hands", "arms", "shield", "about", "waist", "wrist1", "wrist2",
"wield", "hold", "third", "fourth", "r1", "r2"
};
char *flag_string( int bitvector, char * const flagarray[] )
{
static char buf[MAX_STRING_LENGTH];
int x;
buf[0] = '\0';
for ( x = 0; x < 32 ; x++ )
if ( IS_SET( bitvector, 1 << x ) )
{
strcat( buf, flagarray[x] );
strcat( buf, " " );
}
if ( (x=strlen( buf )) > 0 )
buf[--x] = '\0';
return buf;
}
bool can_rmodify( CHAR_DATA *ch, ROOM_INDEX_DATA *room )
{
if ( IS_NPC( ch ) )
return FALSE;
if ( get_trust( ch ) >= MAX_LEVEL - 1 )
return TRUE;
if ( !IS_SET( room->room_flags, ROOM_PROTOTYPE) )
{
send_to_char( "You cannot modify this room.\n\r", ch );
return FALSE;
}
send_to_char( "That room is not in your allocated range.\n\r", ch
);
return FALSE;
}
bool can_oedit( CHAR_DATA *ch, OBJ_INDEX_DATA *obj )
{
if ( IS_NPC( ch ) )
return FALSE;
if ( get_trust( ch ) >= MAX_LEVEL - 1 )
return TRUE;
if ( !IS_OBJ_STAT( obj, ITEM_PROTOTYPE) )
{
send_to_char( "You cannot modify this object.\n\r", ch );
return FALSE;
}
send_to_char( "That object is not in your allocated range.\n\r",
ch );
return FALSE;
}
bool can_mmodify( CHAR_DATA *ch, CHAR_DATA *mob )
{
if ( mob == ch )
return TRUE;
if ( !IS_NPC( mob ) )
{
if ( get_trust( ch ) >= MAX_LEVEL - 1 && get_trust(ch) >
get_trust( mob ) )
return TRUE;
else
send_to_char( "You can't do that.\n\r", ch );
return FALSE;
}
if ( IS_NPC( ch ) )
return FALSE;
if ( get_trust( ch ) >= MAX_LEVEL - 1 )
return TRUE;
if ( !IS_SET( mob->act, ACT_PROTOTYPE) )
{
send_to_char( "You cannot modify this mobile.\n\r", ch );
return FALSE;
}
send_to_char( "That mobile is not in your allocated range.\n\r",
ch );
return FALSE;
}
bool can_medit( CHAR_DATA *ch, MOB_INDEX_DATA *mob )
{
if ( IS_NPC( ch ) )
return FALSE;
if ( get_trust( ch ) >= MAX_LEVEL - 1 )
return TRUE;
if ( !IS_SET( mob->act, ACT_PROTOTYPE) )
{
send_to_char( "You cannot modify this mobile.\n\r", ch );
return FALSE;
}
send_to_char( "That mobile is not in your allocated range.\n\r",
ch );
return FALSE;
}
int get_otype( char *type )
{
int x;
for ( x = 0; x < (sizeof(o_types) / sizeof(o_types[0]) ); x++ )
if ( !str_cmp( type, o_types[x] ) )
return x;
return -1;
}
int get_wearloc( char *type )
{
int x;
for ( x = 0; x < MAX_WEAR; x++ )
if ( !str_cmp( type, wear_locs[x] ) )
return x;
return -1;
}
int get_exflag( char *flag )
{
int x;
for ( x = 0; x <= MAX_EXFLAG; x++ )
if ( !str_cmp( flag, ex_flags[x] ) )
return x;
return -1;
}
int get_rflag( char *flag )
{
int x;
for ( x = 0; x < 32; x++ )
if ( !str_cmp( flag, r_flags[x] ) )
return x;
return -1;
}
int get_oflag( char *flag )
{
int x;
for ( x = 0; x < 32; x++ )
if ( !str_cmp( flag, o_flags[x] ) )
return x;
return -1;
}
int get_wflag( char *flag )
{
int x;
for ( x = 0; x < 32; x++ )
if ( !str_cmp( flag, w_flags[x] ) )
return x;
return -1;
}
int get_actflag( char *flag )
{
int x;
for ( x = 0; x < 32; x++ )
if ( !str_cmp( flag, act_flags[x] ) )
return x;
return -1;
}
int get_plrflag( char *flag )
{
int x;
for ( x = 0; x < 32; x++ )
if ( !str_cmp( flag, plr_flags[x] ) )
return x;
return -1;
}
void do_redit( CHAR_DATA *ch, char *argument )
{
char arg [MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
char arg3[MAX_INPUT_LENGTH];
char buf [MAX_STRING_LENGTH];
ROOM_INDEX_DATA *location, *tmp;
EXTRA_DESCR_DATA *ed;
char dir;
EXIT_DATA *xit, *texit;
int value;
int edir, ekey, evnum;
char *origarg = argument;
if ( !ch->desc )
{
send_to_char( "You have no descriptor.\n\r", ch );
return;
}
switch( ch->substate )
{
default:
break;
case SUB_ROOM_DESC:
location = ch->dest_buf;
if ( !location )
{
bug( "redit: sub_room_desc: NULL ch->dest_buf", 0 );
location = ch->in_room;
}
STRFREE( location->description );
location->description = copy_buffer( ch );
stop_editing( ch );
ch->substate = ch->tempnum;
return;
case SUB_ROOM_EXTRA:
ed = ch->dest_buf;
if ( !ed )
{
bug( "redit: sub_room_extra: NULL ch->dest_buf", 0 );
stop_editing( ch );
return;
}
STRFREE( ed->description );
ed->description = copy_buffer( ch );
stop_editing( ch );
ch->substate = ch->tempnum;
return;
}
location = ch->in_room;
smash_tilde( argument );
argument = one_argument( argument, arg );
if ( ch->substate == SUB_REPEATCMD )
{
if ( arg[0] == '\0' )
{
do_rstat( ch, "" );
return;
}
if ( !str_cmp( arg, "done" ) || !str_cmp( arg, "off" ) )
{
send_to_char( "Redit mode off.\n\r", ch );
if ( ch->pcdata && ch->pcdata->subprompt )
STRFREE( ch->pcdata->subprompt );
ch->substate = SUB_NONE;
return;
}
}
if ( arg[0] == '\0' || !str_cmp( arg, "?" ) )
{
if ( ch->substate == SUB_REPEATCMD )
send_to_char( "Syntax: <field> value\n\r", ch);
else
send_to_char( "Syntax: redit <field> value\n\r", ch);
send_to_char( "\n\r", ch);
send_to_char( "Field being one of:\n\r", ch);
send_to_char( " name desc ed rmed\n\r", ch);
send_to_char( " exit bexit exdesc exflags exname\n\r", ch );
send_to_char( " flags sector rlist exkey\n\r", ch );
return;
}
if ( !can_rmodify( ch, location ) )
return;
if ( !str_cmp( arg, "on" ) )
{
send_to_char( "Redit mode on.\n\r", ch );
ch->substate = SUB_REPEATCMD;
if ( ch->pcdata )
{
if ( ch->pcdata->subprompt )
STRFREE( ch->pcdata->subprompt );
ch->pcdata->subprompt = STRALLOC( "<&CRedit &W#%r&w> %i" );
}
return;
}
if ( !str_cmp( arg, "substate" ) )
{
argument = one_argument( argument, arg2);
if( !str_cmp( arg2, "north" ) )
{
ch->inter_substate = SUB_NORTH;
return;
}
if( !str_cmp( arg2, "east" ) )
{
ch->inter_substate = SUB_EAST;
return;
}
if( !str_cmp( arg2, "south" ) )
{
ch->inter_substate = SUB_SOUTH;
return;
}
if( !str_cmp( arg2, "west" ) )
{
ch->inter_substate = SUB_WEST;
return;
}
if( !str_cmp( arg2, "up" ) )
{
ch->inter_substate = SUB_UP;
return;
}
if( !str_cmp( arg2, "down" ) )
{
ch->inter_substate = SUB_DOWN;
return;
}
send_to_char( " unrecognized substate in redit\n\r", ch);
return;
}
if ( !str_cmp( arg, "name" ) )
{
if ( argument[0] == '\0' )
{
send_to_char( "Set the room name. A very brief single line room description.\n\r", ch );
send_to_char( "Usage: redit name <Room summary>\n\r", ch );
return;
}
STRFREE( location->name );
location->name = STRALLOC( argument );
return;
}
if ( !str_cmp( arg, "desc" ) )
{
if ( ch->substate == SUB_REPEATCMD )
ch->tempnum = SUB_REPEATCMD;
else
ch->tempnum = SUB_NONE;
ch->substate = SUB_ROOM_DESC;
ch->dest_buf = location;
start_editing( ch, location->description );
return;
}
if ( !str_cmp( arg, "ed" ) )
{
if ( !argument || argument[0] == '\0' )
{
send_to_char( "Create an extra description.\n\r", ch );
send_to_char( "You must supply keyword(s).\n\r", ch );
return;
}
CHECK_SUBRESTRICTED( ch );
ed = SetRExtra( location, argument );
if ( ch->substate == SUB_REPEATCMD )
ch->tempnum = SUB_REPEATCMD;
else
ch->tempnum = SUB_NONE;
ch->substate = SUB_ROOM_EXTRA;
ch->dest_buf = ed;
start_editing( ch, ed->description );
return;
}
if ( !str_cmp( arg, "rmed" ) )
{
if ( !argument || argument[0] == '\0' )
{
send_to_char( "Remove an extra description.\n\r", ch );
send_to_char( "You must supply keyword(s).\n\r", ch );
return;
}
if ( DelRExtra( location, argument ) )
send_to_char( "Deleted.\n\r", ch );
else
send_to_char( "Not found.\n\r", ch );
return;
}
if ( !str_cmp( arg, "flags" ) )
{
if ( !argument || argument[0] == '\0' )
{
send_to_char( "Toggle the room flags.\n\r", ch );
send_to_char( "Usage: redit flags <flag> [flag]...\n\r", ch );
return;
}
while ( argument[0] != '\0' )
{
argument = one_argument( argument, arg2 );
value = get_rflag( arg2 );
if ( value < 0 || value > 31 )
{
sprintf( buf, "Unknown flag: %s\n\r", arg2 );
stc(buf, ch);
}
else
{
if ( 1 << value == ROOM_PROTOTYPE
&& get_trust( ch ) < MAX_LEVEL - 1 )
send_to_char( "You cannot change the prototype flag.\n\r",ch );
else
TOGGLE_BIT( location->room_flags, 1 << value );
}
}
return;
}
if ( !str_cmp( arg, "sector" ) )
{
if ( !argument || argument[0] == '\0' )
{
send_to_char( "Set the sector type.\n\r", ch );
send_to_char( "Usage: redit sector <value>\n\r", ch );
return;
}
location->sector_type = atoi( argument );
if ( location->sector_type < 0 || location->sector_type >=
SECT_MAX )
{
location->sector_type = 1;
send_to_char( "Out of range\n\r.", ch );
}
else
send_to_char( "Done.\n\r", ch );
return;
}
if ( !str_cmp( arg, "exkey" ) )
{
argument = one_argument( argument, arg2 );
argument = one_argument( argument, arg3 );
if ( arg2[0] == '\0' || arg3[0] == '\0' )
{
send_to_char( "Usage: redit exkey <dir> <key vnum>\n\r", ch );
return;
}
if ( arg2[0] == '#' )
{
edir = atoi( arg2+1 );
xit = get_exit_num( location, edir );
}
else
{
edir = get_dir( arg2 );
xit = get_exit( location, edir );
}
value = atoi( arg3 );
if ( !xit )
{
send_to_char( "No exit in that direction. Use 'redit exit ...' first.\n\r", ch );
return;
}
xit->key = value;
send_to_char( "Done.\n\r", ch );
return;
}
if ( !str_cmp( arg, "exname" ) )
{
argument = one_argument( argument, arg2 );
if ( arg2[0] == '\0' )
{
send_to_char( "Change or clear exit keywords.\n\r", ch );
send_to_char( "Usage: redit exname <dir> [keywords]\n\r", ch );
return;
}
if ( arg2[0] == '#' )
{
edir = atoi( arg2+1 );
xit = get_exit_num( location, edir );
}
else
{
edir = get_dir( arg2 );
xit = get_exit( location, edir );
}
if ( !xit )
{
send_to_char( "No exit in that direction. Use 'redit exit ...' first.\n\r", ch );
return;
}
STRFREE( xit->keyword );
xit->keyword = STRALLOC( argument );
send_to_char( "Done.\n\r", ch );
return;
}
if ( !str_cmp( arg, "exflags" ) )
{
if ( !argument || argument[0] == '\0' )
{
send_to_char( "Toggle or display exit flags.\n\r", ch );
send_to_char( "Usage: redit exflags <dir> <flag> [flag]...\n\r", ch );
return;
}
argument = one_argument( argument, arg2 );
if ( arg2[0] == '#' )
{
edir = atoi( arg2+1 );
xit = get_exit_num( location, edir );
}
else
{
edir = get_dir( arg2 );
xit = get_exit( location, edir );
}
if ( !xit )
{
send_to_char( "No exit in that direction. Use 'redit exit ...' first.\n\r", ch );
return;
}
if ( argument[0] == '\0' )
{
sprintf( buf, "Flags for exit: direction: %d Keywords: %s Key: %d\n\r[ ",
xit->vdir, xit->keyword, xit->key );
for ( value = 0; value <= MAX_EXFLAG; value++ )
{
if ( IS_SET( xit->exit_info, 1 << value ) )
{
strcat( buf, ex_flags[value] );
strcat( buf, " " );
}
}
strcat( buf, "]\n\r" );
send_to_char( buf, ch );
return;
}
while ( argument[0] != '\0' )
{
argument = one_argument( argument, arg2 );
value = get_exflag( arg2 );
if ( value < 0 || value > MAX_EXFLAG )
{
sprintf( buf, "Unknown flag: %s\n\r", arg2 );
stc(buf, ch);
}
else
TOGGLE_BIT( xit->exit_info, 1 << value );
}
return;
}
if ( !str_cmp( arg, "ex_flags" ) )
{
argument = one_argument( argument, arg2 );
switch(ch->inter_substate)
{
case SUB_EAST : dir = 'e'; edir = 1; break;
case SUB_WEST : dir = 'w'; edir = 3; break;
case SUB_SOUTH: dir = 's'; edir = 2; break;
case SUB_UP : dir = 'u'; edir = 4; break;
case SUB_DOWN : dir = 'd'; edir = 5; break;
default:
case SUB_NORTH: dir = 'n'; edir = 0; break;
}
value = get_exflag(arg2);
if ( value < 0 )
{
send_to_char("Bad exit flag. \n\r", ch);
return;
}
if ( (xit = get_exit(location,edir)) == NULL )
{
sprintf(buf,"exit %c 1",dir);
do_redit(ch,buf);
xit = get_exit(location,edir);
}
TOGGLE_BIT( xit->exit_info, value );
return;
}
if ( !str_cmp( arg, "ex_to_room" ) )
{
argument = one_argument( argument, arg2 );
switch(ch->inter_substate)
{
case SUB_EAST : dir = 'e'; edir = 1; break;
case SUB_WEST : dir = 'w'; edir = 3; break;
case SUB_SOUTH: dir = 's'; edir = 2; break;
case SUB_UP : dir = 'u'; edir = 4; break;
case SUB_DOWN : dir = 'd'; edir = 5; break;
default:
case SUB_NORTH: dir = 'n'; edir = 0; break;
}
evnum = atoi(arg2);
if ( evnum < 1 || evnum > 10032766 )
{
send_to_char( "Invalid room number.\n\r", ch );
return;
}
if ( (tmp = get_room_index( evnum )) == NULL )
{
send_to_char( "Non-existant room.\n\r", ch );
return;
}
if ( (xit = get_exit(location,edir)) == NULL )
{
sprintf(buf,"exit %c 1",dir);
do_redit(ch,buf);
xit = get_exit(location,edir);
}
xit->vnum = evnum;
return;
}
if ( !str_cmp( arg, "ex_key" ) )
{
argument = one_argument( argument, arg2 );
switch(ch->inter_substate)
{
case SUB_EAST : dir = 'e'; edir = 1; break;
case SUB_WEST : dir = 'w'; edir = 3; break;
case SUB_SOUTH: dir = 's'; edir = 2; break;
case SUB_UP : dir = 'u'; edir = 4; break;
case SUB_DOWN : dir = 'd'; edir = 5; break;
default:
case SUB_NORTH: dir = 'n'; edir = 0; break;
}
if ( (xit = get_exit(location,edir)) == NULL )
{
sprintf(buf,"exit %c 1",dir);
do_redit(ch,buf);
xit = get_exit(location,edir);
}
xit->key = atoi( arg2 );
return;
}
if ( !str_cmp( arg, "ex_exdesc" ) )
{
switch(ch->inter_substate)
{
case SUB_EAST : dir = 'e'; edir = 1; break;
case SUB_WEST : dir = 'w'; edir = 3; break;
case SUB_SOUTH: dir = 's'; edir = 2; break;
case SUB_UP : dir = 'u'; edir = 4; break;
case SUB_DOWN : dir = 'd'; edir = 5; break;
default:
case SUB_NORTH: dir = 'n'; edir = 0; break;
}
if ( (xit = get_exit(location, edir)) == NULL )
{
sprintf(buf,"exit %c 1",dir);
do_redit(ch,buf);
}
sprintf(buf,"exdesc %c %s",dir,argument);
do_redit(ch,buf);
return;
}
if ( !str_cmp( arg, "ex_keywords" ) ) /* not called yet */
{
switch(ch->inter_substate)
{
case SUB_EAST : dir = 'e'; edir = 1; break;
case SUB_WEST : dir = 'w'; edir = 3; break;
case SUB_SOUTH: dir = 's'; edir = 2; break;
case SUB_UP : dir = 'u'; edir = 4; break;
case SUB_DOWN : dir = 'd'; edir = 5; break;
default:
case SUB_NORTH: dir = 'n'; edir = 0; break;
}
if ( (xit = get_exit(location, edir)) == NULL )
{
sprintf(buf, "exit %c 1", dir);
do_redit(ch,buf);
if ( (xit = get_exit(location, edir)) == NULL )
return;
}
sprintf( buf, "%s %s", xit->keyword, argument );
STRFREE( xit->keyword );
xit->keyword = STRALLOC( buf );
return;
}
if ( !str_cmp( arg, "exit" ) )
{
bool addexit, numnotdir;
argument = one_argument( argument, arg2 );
argument = one_argument( argument, arg3 );
if ( !arg2 || arg2[0] == '\0' )
{
send_to_char( "Create, change or remove an exit.\n\r", ch );
send_to_char( "Usage: redit exit <dir> [room] [flags] [key] [keywords]\n\r", ch );
return;
}
addexit = numnotdir = FALSE;
switch( arg2[0] )
{
default: edir = get_dir(arg2); break;
case '+': edir = get_dir(arg2+1); addexit = TRUE; break;
case '#': edir = atoi(arg2+1); numnotdir = TRUE; break;
}
if ( !arg3 || arg3[0] == '\0' )
evnum = 0;
else
evnum = atoi( arg3 );
if ( numnotdir )
{
if ( (xit = get_exit_num(location, edir)) != NULL )
edir = xit->vdir;
}
else
xit = get_exit(location, edir);
if ( !evnum )
{
if ( xit )
{
extract_exit(location, xit);
send_to_char( "Exit removed.\n\r", ch );
return;
}
send_to_char( "No exit in that direction.\n\r", ch );
return;
}
if ( evnum < 1 || evnum > 10032766 )
{
send_to_char( "Invalid room number.\n\r", ch );
return;
}
if ( (tmp = get_room_index( evnum )) == NULL )
{
send_to_char( "Non-existant room.\n\r", ch );
return;
}
if ( addexit || !xit )
{
if ( numnotdir )
{
send_to_char( "Cannot add an exit by number, sorry.\n\r",
ch );
return;
}
if ( addexit && xit && get_exit_to(location, edir, tmp->vnum)
)
{
send_to_char( "There is already an exit in that direction leading to that location.\n\r", ch );
return;
}
xit = make_exit( location, tmp, edir );
xit->keyword = STRALLOC( "" );
xit->description = STRALLOC( "" );
xit->key = -1;
xit->exit_info = 0;
act( "$n reveals a hidden passage!", ch, NULL, NULL, TO_ROOM
);
}
else
act( "Something is different...", ch, NULL, NULL, TO_ROOM );
if ( xit->to_room != tmp )
{
xit->to_room = tmp;
xit->vnum = evnum;
texit = get_exit_to( xit->to_room, rev_dir[edir],
location->vnum );
if ( texit )
{
texit->rexit = xit;
xit->rexit = texit;
}
}
argument = one_argument( argument, arg3 );
if ( arg3 && arg3[0] != '\0' )
xit->exit_info = atoi( arg3 );
if ( argument && argument[0] != '\0' )
{
one_argument( argument, arg3 );
ekey = atoi( arg3 );
if ( ekey != 0 || arg3[0] == '0' )
{
argument = one_argument( argument, arg3 );
xit->key = ekey;
}
if ( argument && argument[0] != '\0' )
{
STRFREE( xit->keyword );
xit->keyword = STRALLOC( argument );
}
}
send_to_char( "Done.\n\r", ch );
return;
}
/*
* Twisted and evil, but works -Thoric
* Makes an exit, and the reverse in one shot.
*/
if ( !str_cmp( arg, "bexit" ) )
{
EXIT_DATA *xit, *rxit;
char tmpcmd[MAX_INPUT_LENGTH];
ROOM_INDEX_DATA *tmploc;
int vnum, exnum;
char rvnum[MAX_INPUT_LENGTH];
bool numnotdir;
argument = one_argument( argument, arg2 );
argument = one_argument( argument, arg3 );
if ( !arg2 || arg2[0] == '\0' )
{
send_to_char( "Create, change or remove a two-way exit.\n\r",
ch );
send_to_char( "Usage: redit bexit <dir> [room] [flags] [key] [keywords]\n\r", ch );
return;
}
numnotdir = FALSE;
switch( arg2[0] )
{
default:
edir = get_dir( arg2 );
break;
case '#':
numnotdir = TRUE;
edir = atoi( arg2+1 );
break;
case '+':
edir = get_dir( arg2+1 );
break;
}
tmploc = location;
exnum = edir;
if ( numnotdir )
{
if ( (xit = get_exit_num(tmploc, edir)) != NULL )
edir = xit->vdir;
}
else
xit = get_exit(tmploc, edir);
rxit = NULL;
vnum = 0;
rvnum[0] = '\0';
if ( xit )
{
vnum = xit->vnum;
if ( arg3[0] != '\0' )
sprintf( rvnum, "%d", tmploc->vnum );
if ( xit->to_room )
rxit = get_exit(xit->to_room, rev_dir[edir]);
else
rxit = NULL;
}
sprintf( tmpcmd, "exit %s %s %s", arg2, arg3, argument );
do_redit( ch, tmpcmd );
if ( numnotdir )
xit = get_exit_num(tmploc, exnum);
else
xit = get_exit(tmploc, edir);
if ( !rxit && xit )
{
vnum = xit->vnum;
if ( arg3[0] != '\0' )
sprintf( rvnum, "%d", tmploc->vnum );
if ( xit->to_room )
rxit = get_exit(xit->to_room, rev_dir[edir]);
else
rxit = NULL;
}
if ( vnum )
{
sprintf( tmpcmd, "%d redit exit %d %s %s",
vnum,
rev_dir[edir],
rvnum,
argument );
do_at( ch, tmpcmd );
}
return;
}
if ( !str_cmp( arg, "exdesc" ) )
{
argument = one_argument( argument, arg2 );
if ( !arg2 || arg2[0] == '\0' )
{
send_to_char( "Create or clear a description for an exit.\n\r", ch );
send_to_char( "Usage: redit exdesc <dir> [description]\n\r", ch );
return;
}
if ( arg2[0] == '#' )
{
edir = atoi( arg2+1 );
xit = get_exit_num( location, edir );
}
else
{
edir = get_dir( arg2 );
xit = get_exit( location, edir );
}
if ( xit )
{
STRFREE( xit->description );
if ( !argument || argument[0] == '\0' )
xit->description = STRALLOC( "" );
else
{
sprintf( buf, "%s\n\r", argument );
xit->description = STRALLOC( buf );
}
send_to_char( "Done.\n\r", ch );
return;
}
send_to_char( "No exit in that direction. Use 'redit exit ...' first.\n\r", ch );
return;
}
/*
* Generate usage message.
*/
if ( ch->substate == SUB_REPEATCMD )
{
ch->substate = SUB_RESTRICTED;
interpret( ch, origarg );
ch->substate = SUB_REPEATCMD;
ch->last_cmd = do_redit;
}
else
do_redit( ch, "" );
return;
}
void do_mset( CHAR_DATA *ch, char *argument )
{
char arg1 [MAX_INPUT_LENGTH];
char arg2 [MAX_INPUT_LENGTH];
char arg3 [MAX_INPUT_LENGTH];
char buf [MAX_STRING_LENGTH];
CHAR_DATA *victim;
int value;
int minattr, maxattr;
bool lockvictim;
char *origarg = argument;
if ( IS_NPC( ch ) )
{
send_to_char( "Mob's can't mset\n\r", ch );
return;
}
if ( !ch->desc )
{
send_to_char( "You have no descriptor\n\r", ch );
return;
}
switch( ch->substate )
{
default:
break;
case SUB_MOB_DESC:
if ( !ch->dest_buf )
{
send_to_char( "Fatal error: report to Thoric.\n\r", ch );
bug( "do_mset: sub_mob_desc: NULL ch->dest_buf", 0 );
ch->substate = SUB_NONE;
return;
}
victim = ch->dest_buf;
if ( victim == NULL )
{
stc("Your victim doesn't exist!\n\r",ch);
stop_editing(ch);
return;
}
STRFREE( victim->description );
victim->description = copy_buffer( ch );
if ( IS_NPC(victim) && IS_SET( victim->act, ACT_PROTOTYPE ) )
{
STRFREE( victim->pIndexData->description );
victim->pIndexData->description = QUICKLINK(victim->description );
}
stop_editing( ch );
ch->substate = ch->tempnum;
return;
}
victim = NULL;
lockvictim = FALSE;
smash_tilde( argument );
if ( ch->substate == SUB_REPEATCMD )
{
victim = ch->dest_buf;
if ( victim == POS_DEAD )
{
send_to_char( "Your victim died!\n\r", ch );
victim = NULL;
argument = "done";
}
if ( argument[0] == '\0' || !str_cmp( argument, " " )
|| !str_cmp( argument, "stat" ) )
{
if ( victim )
do_mstat( ch, victim->name );
else
send_to_char( "No victim selected. Type '?' for help.\n\r", ch );
return;
}
if ( !str_cmp( argument, "done" ) || !str_cmp( argument, "off" ) )
{
send_to_char( "Mset mode off.\n\r", ch );
ch->substate = SUB_NONE;
ch->dest_buf = NULL;
if ( ch->pcdata && ch->pcdata->subprompt )
STRFREE( ch->pcdata->subprompt );
return;
}
}
if ( victim )
{
lockvictim = TRUE;
strcpy( arg1, victim->name );
argument = one_argument( argument, arg2 );
strcpy( arg3, argument );
}
else
{
lockvictim = FALSE;
argument = one_argument( argument, arg1 );
argument = one_argument( argument, arg2 );
strcpy( arg3, argument );
}
if ( !str_cmp( arg1, "on" ) )
{
send_to_char( "Syntax: mset <victim|vnum> on.\n\r", ch );
return;
}
if ( arg1[0] == '\0' || (arg2[0] == '\0' && ch->substate != SUB_REPEATCMD)
|| !str_cmp( arg1, "?" ) )
{
if ( ch->substate == SUB_REPEATCMD )
{
if ( victim )
send_to_char( "Syntax: <field> <value>\n\r", ch );
else
send_to_char( "Syntax: <victim> <field> <value>\n\r", ch );
}
else
send_to_char( "Syntax: mset <victim> <field> <value>\n\r", ch );
send_to_char( "\n\r", ch );
send_to_char( "Field being one of:\n\r", ch );
send_to_char( "drowpoints demonpoints demonsouls\n\r", ch);
send_to_char( "str int wis dex con sex", ch);
send_to_char( "hp mana move primal magebits\n\r", ch);
send_to_char( "drunk thirst hitroll quest\n\r", ch);
send_to_char( "name short long description title spec\n\r", ch);
send_to_char( "level\n\r", ch);
send_to_char( "I got pissed off not being able to do any of the msets.\n\r", ch);
send_to_char( "whichever other one's work note me and I'll add them.\n\r", ch);
return;
}
if ( !victim && get_trust( ch ) < MAX_LEVEL - 3 )
{
if ( ( victim = get_char_room( ch, arg1 ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
}
else
if ( !victim )
{
if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
{
send_to_char( "No one like that in all the realms.\n\r", ch );
return;
}
}
if ( get_trust( ch ) < get_trust( victim ) && !IS_NPC( victim ) )
{
send_to_char( "You can't do that!\n\r", ch );
ch->dest_buf = NULL;
return;
}
if ( lockvictim )
ch->dest_buf = victim;
if ( IS_NPC(victim) )
{
minattr = 1;
maxattr = 25;
}
else
{
minattr = 3;
maxattr = 18;
}
if ( !str_cmp( arg2, "on" ) )
{
CHECK_SUBRESTRICTED( ch );
sprintf( buf, "Mset mode on. (Editing %s).\n\r",
victim->name );
stc(buf, ch);
ch->substate = SUB_REPEATCMD;
ch->dest_buf = victim;
return;
}
value = is_number( arg3 ) ? atoi( arg3 ) : -1;
if ( atoi(arg3) < -1 && value == -1 )
value = atoi(arg3);
if ( !str_cmp( arg2, "sex" ) )
{
if ( value < 0 || value > 2 )
{
send_to_char( "Sex range is 0 to 2.\n\r", ch );
return;
}
victim->sex = value;
if ( IS_NPC(victim) && IS_SET( victim->act, ACT_PROTOTYPE ) )
victim->pIndexData->sex = value;
return;
}
if ( !str_cmp( arg2, "armor" ) )
{
if ( value < -300 || value > 300 )
{
send_to_char( "AC range is -300 to 300.\n\r", ch );
return;
}
victim->armor = value;
if ( IS_NPC(victim) && IS_SET( victim->act, ACT_PROTOTYPE ) )
victim->pIndexData->ac = value;
return;
}
if ( !str_cmp( arg2, "level" ) )
{
if ( IS_NPC(victim) )
{
send_to_char( "Only on PC's.\n\r", ch );
return;
}
if ( value < 0 || value > 12 )
{
stc("You can only set player levels from 0 - 12.\n\r",ch);
return;
}
victim->level = value;
stc("Level set.\n\r",ch);
return;
}
/********* UNAUTHORIZED CODE FROM LOIMOS *********/
if ( !str_cmp( arg2, "dna" ) )
{
if ( value < 0 || value > 1000000 )
{
stc("Value must be in range from 0 to 1,000,000.\n\r", ch);
return;
}
victim->pcdata->powers[ALIEN_DNA] = value;
stc("DNA set.\n\r", ch);
return;
}
if ( !str_cmp( arg2, "size" ) )
{
if ( value < 0 || value > 10 )
{
stc("Value must be in the range of 0 - 10.\n\r", ch);
return;
}
if ( (GET_POWERS(victim, ALIEN_SIZE) < 10 ) )
{
stc("Your size has been altered.\n\r", victim);
stc("Size set.\n\r", ch);
GET_POWERS(victim, ALIEN_SIZE) = value;
return;
}
else
{
stc("They have already reached their maximum size.\n\r", ch);
return;
}
}
/***************** END LOIMOS' CODE **************/
if ( !str_cmp( arg2, "hitroll" ) )
{
victim->hitroll = URANGE(0, value, 85);
if ( IS_NPC(victim) && IS_SET( victim->act, ACT_PROTOTYPE ) )
victim->pIndexData->hitroll = victim->hitroll;
return;
}
if ( !str_cmp( arg2, "hp" ) )
{
if ( value < 1 || value > 30000 )
{
send_to_char( "Hp range is 1 to 30,000 hit points.\n\r", ch );
return;
}
victim->max_hit = value;
return;
}
if (!str_cmp( arg2, "primal") )
{
if (value < 1 || value > 5000)
{
send_to_char( "Primal can only be set between 1 and 5000 points.\n\r", ch);
return;
}
victim->practice = value;
return;
}
if ( !str_cmp( arg2, "exp") )
{
if (value < 1 || value > 99000000)
{
send_to_char("Experience can only be set between 1 and 99,000,000.\n\r", ch);
return;
}
victim->exp = value;
return;
}
if ( !str_cmp( arg2, "mana" ) )
{
if ( value < 0 || value > 30000 )
{
send_to_char( "Mana range is 0 to 30,000 mana points.\n\r", ch);
return;
}
victim->max_mana = value;
return;
}
if ( !str_cmp( arg2, "move" ) )
{
if ( value < 0 || value > 30000 )
{
send_to_char( "Move range is 0 to 30,000 move points.\n\r", ch);
return;
}
victim->max_move = value;
return;
}
if ( !str_cmp( arg2, "align" ) )
{
if ( value < -1000 || value > 1000 )
{
send_to_char( "Alignment range is -1000 to 1000.\n\r", ch );
return;
}
victim->alignment = value;
if ( IS_NPC(victim) && IS_SET( victim->act, ACT_PROTOTYPE ) )
victim->pIndexData->alignment = value;
return;
}
if ( !str_cmp( arg2, "thirst" ) )
{
if ( IS_NPC(victim) )
{
send_to_char( "Not on NPC's.\n\r", ch );
return;
}
if ( value < 0 || value > 100 )
{
send_to_char( "Thirst range is 0 to 100.\n\r", ch );
return;
}
victim->pcdata->condition[COND_THIRST] = value;
return;
}
if ( !str_cmp( arg2, "drunk" ) )
{
if ( IS_NPC(victim) )
{
send_to_char( "Not on NPC's.\n\r", ch );
return;
}
if ( value < 0 || value > 100 )
{
send_to_char( "Drunk range is 0 to 100.\n\r", ch );
return;
}
victim->pcdata->condition[COND_DRUNK] = value;
return;
}
if ( !str_cmp( arg2, "full" ) )
{
if ( IS_NPC(victim) )
{
send_to_char( "Not on NPC's.\n\r", ch );
return;
}
if ( value < 0 || value > 100 )
{
send_to_char( "Full range is 0 to 100.\n\r", ch );
return;
}
victim->pcdata->condition[COND_FULL] = value;
return;
}
if ( !str_cmp( arg2, "blood" ) )
{
if ( IS_NPC(victim) )
{
send_to_char( "Not on NPC's.\n\r", ch );
return;
}
if ( value < 0 || value > 2000 )
{
stc("Blood range is 0 to 2000.\n\r",ch);
return;
}
victim->pcdata->condition[COND_THIRST] = value;
return;
}
if ( !str_cmp( arg2, "name" ) )
{
if ( !IS_NPC(victim) && get_trust( ch ) < MAX_LEVEL )
{
send_to_char( "Not on PC's.\n\r", ch );
return;
}
STRFREE( victim->name );
victim->name = STRALLOC( arg3 );
if ( IS_NPC(victim) && IS_SET( victim->act, ACT_PROTOTYPE ) )
{
STRFREE( victim->pIndexData->player_name );
victim->pIndexData->player_name = STRALLOC( arg3 );
}
return;
}
if ( !str_cmp( arg2, "short" ) )
{
STRFREE( victim->short_descr );
victim->short_descr = STRALLOC( arg3 );
if ( IS_NPC(victim) && IS_SET( victim->act, ACT_PROTOTYPE ) )
{
STRFREE( victim->pIndexData->short_descr );
victim->pIndexData->short_descr = QUICKLINK( victim->short_descr );
}
return;
}
if ( !str_cmp( arg2, "long" ) )
{
STRFREE( victim->long_descr );
strcpy( buf, arg3 );
strcat( buf, "\n\r" );
victim->long_descr = STRALLOC( buf );
if ( IS_NPC(victim) && IS_SET( victim->act, ACT_PROTOTYPE ) )
{
STRFREE( victim->pIndexData->long_descr );
victim->pIndexData->long_descr = QUICKLINK( victim->long_descr
);
}
return;
}
if ( !str_cmp( arg2, "description" ) )
{
if ( arg3[0] )
{
STRFREE( victim->description );
victim->description = STRALLOC( arg3 );
if ( IS_NPC( victim ) && IS_SET( victim->act, ACT_PROTOTYPE ) )
{
STRFREE(victim->pIndexData->description );
victim->pIndexData->description = QUICKLINK(
victim->description );
}
return;
}
CHECK_SUBRESTRICTED( ch );
if ( ch->substate == SUB_REPEATCMD )
ch->tempnum = SUB_REPEATCMD;
else
ch->tempnum = SUB_NONE;
ch->substate = SUB_MOB_DESC;
ch->dest_buf = victim;
start_editing( ch, victim->description );
return;
}
if ( !str_cmp( arg2, "title" ) )
{
if ( IS_NPC(victim) )
{
send_to_char( "Not on NPC's.\n\r", ch );
return;
}
set_title( victim, arg3 );
return;
}
if ( !str_cmp( arg2, "spec" ) )
{
if ( !IS_NPC(victim) )
{
send_to_char( "Not on PC's.\n\r", ch );
return;
}
if ( !str_cmp( arg3, "none" ) )
{
victim->spec_fun = NULL;
send_to_char( "Special function removed.\n\r", ch );
if ( IS_NPC(victim) && IS_SET( victim->act, ACT_PROTOTYPE ) )
victim->pIndexData->spec_fun = victim->spec_fun;
return;
}
if ( ( victim->spec_fun = spec_lookup( arg3 ) ) == 0 )
{
send_to_char( "No such spec fun.\n\r", ch );
return;
}
if ( IS_NPC(victim) && IS_SET( victim->act, ACT_PROTOTYPE ) )
victim->pIndexData->spec_fun = victim->spec_fun;
return;
}
/*
* Generate usage message.
*/
if ( ch->substate == SUB_REPEATCMD )
{
ch->substate = SUB_RESTRICTED;
interpret( ch, origarg );
ch->substate = SUB_REPEATCMD;
ch->last_cmd = do_mset;
}
else
do_mset( ch, "" );
return;
}
void do_ocreate( CHAR_DATA *ch, char *argument )
{
char arg [MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
OBJ_INDEX_DATA *pObjIndex;
OBJ_DATA *obj;
int vnum, cvnum;
if ( IS_NPC(ch) )
{
send_to_char( "Mobiles cannot create.\n\r", ch );
return;
}
argument = one_argument( argument, arg );
vnum = is_number( arg ) ? atoi( arg ) : -1;
if ( vnum == -1 || !argument || argument[0] == '\0' )
{
send_to_char( "Usage: ocreate <vnum> [copy vnum] <item name>\n\r", ch );
return;
}
if ( vnum < 1 || vnum > 2000000 )
{
send_to_char( "Bad number.\n\r", ch );
return;
}
one_argument( argument, arg2 );
cvnum = atoi( arg2 );
if ( cvnum != 0 )
argument = one_argument( argument, arg2 );
if ( cvnum < 1 )
cvnum = 0;
if ( get_obj_index( vnum ) )
{
send_to_char( "An object with that number already exists.\n\r", ch );
return;
}
if ( IS_NPC( ch ) )
return;
if ( get_trust( ch ) < LEVEL_IMMORTAL )
{
send_to_char( "Sorry, No thanks..\n\r", ch );
return;
}
pObjIndex = make_object( vnum, cvnum, argument );
if ( !pObjIndex )
{
send_to_char( "Error.\n\r", ch );
log_string( "do_ocreate: make_object failed." );
return;
}
obj = create_object( pObjIndex, get_trust(ch) );
obj_to_char( obj, ch );
act( "$n makes some ancient arcane gestures, and opens $s hands to reveal $p!", ch, obj, NULL, TO_ROOM );
act( "You make some ancient arcane gestures, and open your hands to reveal $p!", ch, obj, NULL, TO_CHAR );
}
void do_mcreate( CHAR_DATA *ch, char *argument )
{
char arg [MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
MOB_INDEX_DATA *pMobIndex;
CHAR_DATA *mob;
int vnum, cvnum;
if ( IS_NPC(ch) )
{
send_to_char( "Mobiles cannot create.\n\r", ch );
return;
}
argument = one_argument( argument, arg );
vnum = is_number( arg ) ? atoi( arg ) : -1;
if ( vnum == -1 || !argument || argument[0] == '\0' )
{
send_to_char( "Usage: mcreate <vnum> [cvnum] <mobile name>\n\r", ch );
return;
}
if ( vnum < 1 || vnum > 2000000 )
{
send_to_char( "Bad number.\n\r", ch );
return;
}
one_argument( argument, arg2 );
cvnum = atoi( arg2 );
if ( cvnum != 0 )
argument = one_argument( argument, arg2 );
if ( cvnum < 1 )
cvnum = 0;
if ( get_mob_index( vnum ) )
{
send_to_char( "A mobile with that number already exists.\n\r", ch );
return;
}
if ( IS_NPC( ch ) )
return;
if ( get_trust( ch ) < LEVEL_IMMORTAL )
{
send_to_char( "No thanks.\n\r", ch );
return;
}
pMobIndex = make_mobile( vnum, cvnum, argument );
if ( !pMobIndex )
{
send_to_char( "Error.\n\r", ch );
log_string( "do_mcreate: make_mobile failed." );
return;
}
mob = create_mobile( pMobIndex );
char_to_room( mob, ch->in_room );
act( "$n waves $s arms about, and $N appears at $s command!", ch, NULL, mob, TO_ROOM );
act( "You wave your arms about, and $N appears at your command!", ch, NULL, mob, TO_CHAR );
}
/*
* Simple but nice and handle line editor. -Thoric
*/
void edit_buffer( CHAR_DATA *ch, char *argument )
{
DESCRIPTOR_DATA *d;
EDITOR_DATA *edit;
char cmd[MAX_INPUT_LENGTH];
char buf[MAX_INPUT_LENGTH];
sh_int x, line, max_buf_lines;
bool save;
if ( (d = ch->desc) == NULL )
{
send_to_char( "You have no descriptor.\n\r", ch );
return;
}
if ( d->connected != CON_EDITING )
{
send_to_char( "You can't do that!\n\r", ch );
bug( "Edit_buffer: d->connected != CON_EDITING", 0 );
return;
}
if ( ch->substate <= SUB_PAUSE )
{
send_to_char( "You can't do that!\n\r", ch );
sprintf(buf,"Edit_buffer: illegal ch->substate (%d)", ch->substate
);
bug(buf,0);
d->connected = CON_PLAYING;
return;
}
if ( !ch->editor )
{
send_to_char( "You can't do that!\n\r", ch );
bug( "Edit_buffer: null editor", 0 );
d->connected = CON_PLAYING;
return;
}
edit = ch->editor;
save = FALSE;
max_buf_lines = 24;
if ( ch->substate == SUB_MPROG_EDIT || ch->substate == SUB_HELP_EDIT )
max_buf_lines = 48;
if ( argument[0] == '/' || argument[0] == '\\' )
{
one_argument( argument, cmd );
if ( !str_cmp( cmd+1, "?" ) )
{
send_to_char( "Editing commands\n\r---------------------------------\n\r", ch );
send_to_char( "/l list buffer\n\r", ch );
send_to_char( "/c clear buffer\n\r", ch );
send_to_char( "/d [line] delete line\n\r", ch );
send_to_char( "/g <line> goto line\n\r", ch );
send_to_char( "/i <line> insert line\n\r", ch );
send_to_char( "/r <old> <new> global replace\n\r", ch );
send_to_char( "/a abort editing\n\r", ch );
if ( get_trust(ch) > MAX_LEVEL - 4 )
send_to_char( "/! <command> execute command (do not use another editing command)\n\r", ch );
send_to_char( "/s save buffer\n\r\n\r> ",ch );
return;
}
if ( !str_cmp( cmd+1, "c" ) )
{
memset( edit, '\0', sizeof(EDITOR_DATA) );
edit->numlines = 0;
edit->on_line = 0;
send_to_char( "Buffer cleared.\n\r> ", ch );
return;
}
if ( !str_cmp( cmd+1, "r" ) )
{
char word1[MAX_INPUT_LENGTH];
char word2[MAX_INPUT_LENGTH];
char *sptr, *wptr, *lwptr;
int x, count, wordln, word2ln, lineln;
sptr = one_argument( argument, word1 );
sptr = one_argument( sptr, word1 );
sptr = one_argument( sptr, word2 );
if ( word1[0] == '\0' || word2[0] == '\0' )
{
send_to_char( "Need word to replace, and replacement.\n\r>", ch );
return;
}
if ( strcmp( word1, word2 ) == 0 )
{
send_to_char( "Done.\n\r> ", ch );
return;
}
count = 0; wordln = strlen(word1); word2ln = strlen(word2);
sprintf( buf, "Replacing all occurrences of %s with %s...\n\r", word1, word2 );
stc(buf, ch);
for ( x = edit->on_line; x < edit->numlines; x++ )
{
lwptr = edit->line[x];
while ( (wptr = strstr( lwptr, word1 )) != NULL )
{
sptr = lwptr;
lwptr = wptr + wordln;
sprintf( buf, "%s%s", word2, wptr + wordln );
lineln = wptr - edit->line[x] - wordln;
++count;
if ( strlen(buf) + lineln > 79 )
{
lineln = UMAX(0, (79 - strlen(buf)));
buf[lineln] = '\0';
break;
}
else
lineln = strlen(buf);
buf[lineln] = '\0';
strcpy( wptr, buf );
}
}
sprintf( buf, "Found and replaced %d occurrence(s).\n\r> ", count );
stc(buf, ch);
return;
}
if ( !str_cmp( cmd+1, "i" ) )
{
if ( edit->numlines >= max_buf_lines )
send_to_char( "Buffer is full.\n\r> ", ch );
else
{
if ( argument[2] == ' ' )
line = atoi( argument + 2 ) - 1;
else
line = edit->on_line;
if ( line < 0 )
line = edit->on_line;
if ( line < 0 || line > edit->numlines )
send_to_char( "Out of range.\n\r> ", ch );
else
{
for ( x = ++edit->numlines; x > line; x-- )
strcpy( edit->line[x], edit->line[x-1] );
strcpy( edit->line[line], "" );
send_to_char( "Line inserted.\n\r> ", ch );
}
}
return;
}
if ( !str_cmp( cmd+1, "d" ) )
{
if ( edit->numlines == 0 )
send_to_char( "Buffer is empty.\n\r> ", ch );
else
{
if ( argument[2] == ' ' )
line = atoi( argument + 2 ) - 1;
else
line = edit->on_line;
if ( line < 0 )
line = edit->on_line;
if ( line < 0 || line > edit->numlines )
send_to_char( "Out of range.\n\r> ", ch );
else
{
if ( line == 0 && edit->numlines == 1 )
{
memset( edit, '\0', sizeof(EDITOR_DATA) );
edit->numlines = 0;
edit->on_line = 0;
send_to_char( "Line deleted.\n\r> ", ch );
return;
}
for ( x = line; x < (edit->numlines - 1); x++ )
strcpy( edit->line[x], edit->line[x+1] );
strcpy( edit->line[edit->numlines--], "" );
if ( edit->on_line > edit->numlines )
edit->on_line = edit->numlines;
send_to_char( "Line deleted.\n\r> ", ch );
}
}
return;
}
if ( !str_cmp( cmd+1, "g" ) )
{
if ( edit->numlines == 0 )
send_to_char( "Buffer is empty.\n\r> ", ch );
else
{
if ( argument[2] == ' ' )
line = atoi( argument + 2 ) - 1;
else
{
send_to_char( "Goto what line?\n\r> ", ch );
return;
}
if ( line < 0 )
line = edit->on_line;
if ( line < 0 || line > edit->numlines )
send_to_char( "Out of range.\n\r> ", ch );
else
{
edit->on_line = line;
sprintf( buf, "(On line %d)\n\r> ", line+1 );
stc(buf,ch);
}
}
return;
}
if ( !str_cmp( cmd+1, "l" ) )
{
if ( edit->numlines == 0 )
send_to_char( "Buffer is empty.\n\r> ", ch );
else
{
send_to_char( "------------------\n\r", ch );
for ( x = 0; x < edit->numlines; x++ )
{
sprintf( buf, "%2d> %s\n\r", x+1, edit->line[x] );
stc(buf, ch);
}
send_to_char( "------------------\n\r> ", ch );
}
return;
}
if ( !str_cmp( cmd+1, "a" ) )
{
send_to_char( "\n\rAborting... ", ch );
stop_editing( ch );
return;
}
if ( get_trust(ch) > LEVEL_IMMORTAL && !str_cmp( cmd+1, "!" ) )
{
int substate = ch->substate;
ch->substate = SUB_RESTRICTED;
interpret(ch, argument+3);
ch->substate = substate;
send_to_char( "\n\r> ", ch );
return;
}
if ( !str_cmp( cmd+1, "s" ) )
{
d->connected = CON_PLAYING;
do_hedit(ch, "");
if ( !ch->last_cmd )
return;
(*ch->last_cmd) ( ch, "" );
return;
}
}
if ( edit->size + strlen(argument) + 1 >= MAX_STRING_LENGTH - 1 )
send_to_char( "You buffer is full.\n\r", ch );
else
{
if ( strlen(argument) > 79 )
{
strncpy( buf, argument, 79 );
buf[79] = 0;
send_to_char( "(Long line trimmed)\n\r> ", ch );
}
else
strcpy( buf, argument );
strcpy( edit->line[edit->on_line++], buf );
if ( edit->on_line > edit->numlines )
edit->numlines++;
if ( edit->numlines > max_buf_lines )
{
edit->numlines = max_buf_lines;
send_to_char( "Buffer full.\n\r", ch );
save = TRUE;
}
}
if ( save )
{
d->connected = CON_PLAYING;
if ( !ch->last_cmd )
return;
(*ch->last_cmd) ( ch, "" );
return;
}
send_to_char( "> ", ch );
}
/*
* Remove carriage returns from a line
*/
char *strip_cr( char *str )
{
static char newstr[MAX_STRING_LENGTH];
int i, j;
for ( i=j=0; str[i] != '\0'; i++ )
if ( str[i] != '\r' )
{
newstr[j++] = str[i];
}
newstr[j] = '\0';
return newstr;
}
void smush_tilde( char *str )
{
int len;
char last;
char *strptr;
strptr = str;
len = strlen( str );
if ( len )
last = strptr[len-1];
else
last = '\0';
for ( ; *str != '\0'; str++ )
{
if ( *str == '~' )
*str = '-';
}
if ( len )
strptr[len-1] = last;
return;
}
void start_editing( CHAR_DATA *ch, char *data )
{
EDITOR_DATA *edit;
sh_int lines, size, lpos;
char c;
if ( !ch->desc )
{
bug( "Fatal: start_editing: no desc", 0 );
return;
}
if ( ch->substate == SUB_RESTRICTED )
bug( "NOT GOOD: start_editing: ch->substate == SUB_RESTRICTED", 0 );
send_to_char( "Begin entering your text now (/? = help /s = save /c = clear /l = list)\n\r", ch );
send_to_char( "-----------------------------------------------------------------------\n\r> ", ch );
if ( ch->editor )
stop_editing( ch );
CREATE( edit, EDITOR_DATA, 1 );
edit->numlines = 0;
edit->on_line = 0;
edit->size = 0;
size = 0; lpos = 0; lines = 0;
if ( !data )
bug("editor: data is NULL!\n\r",0);
else
for ( ;; )
{
c = data[size++];
if ( c == '\0' )
{
edit->line[lines][lpos] = '\0';
break;
}
else
if ( c == '\r' );
else
if ( c == '\n' || lpos > 78)
{
edit->line[lines][lpos] = '\0';
lines++;
lpos = 0;
}
else
edit->line[lines][lpos++] = c;
if ( lines >= 49 || size > 4096 )
{
edit->line[lines][lpos] = '\0';
break;
}
}
edit->numlines = lines;
edit->size = size;
edit->on_line = lines;
ch->editor = edit;
ch->desc->connected = CON_EDITING;
}
char *copy_buffer( CHAR_DATA *ch )
{
char buf[MAX_STRING_LENGTH];
char tmp[100];
sh_int x, len;
if ( !ch )
{
bug( "copy_buffer: null ch", 0 );
return STRALLOC( "" );
}
if ( !ch->editor )
{
bug( "copy_buffer: null editor", 0 );
return STRALLOC( "" );
}
buf[0] = '\0';
for ( x = 0; x < ch->editor->numlines; x++ )
{
strcpy( tmp, ch->editor->line[x] );
smush_tilde( tmp );
len = strlen(tmp);
if ( tmp && tmp[len-1] == '~' )
tmp[len-1] = '\0';
else
strcat( tmp, "\n\r" );
strcat( buf, tmp );
}
return STRALLOC( buf );
}
void stop_editing( CHAR_DATA *ch )
{
DISPOSE( ch->editor );
ch->editor = NULL;
send_to_char( "Done.\n\r", ch );
ch->dest_buf = NULL;
ch->spare_ptr = NULL;
ch->substate = SUB_NONE;
if ( !ch->desc )
{
bug( "Fatal: stop_editing: no desc", 0 );
return;
}
ch->desc->connected = CON_PLAYING;
}
/*
* Moved into a separate function so it can be used for other things
* ie: online help editing -Thoric
*/
HELP_DATA *get_help( CHAR_DATA *ch, char *argument )
{
char argall[MAX_INPUT_LENGTH];
char argone[MAX_INPUT_LENGTH];
char argnew[MAX_INPUT_LENGTH];
HELP_DATA *pHelp;
int lev;
if ( argument[0] == '\0' )
argument = "summary";
if ( isdigit(argument[0]) )
{
lev = number_argument( argument, argnew );
argument = argnew;
}
else
lev = -2;
/*
* Tricky argument handling so 'help a b' doesn't match a.
*/
argall[0] = '\0';
while ( argument[0] != '\0' )
{
argument = one_argument( argument, argone );
if ( argall[0] != '\0' )
strcat( argall, " " );
strcat( argall, argone );
}
for ( pHelp = first_help; pHelp; pHelp = pHelp->next )
{
if ( pHelp->level > get_trust( ch ) )
continue;
if ( lev != -2 && pHelp->level != lev )
continue;
if ( is_name( argall, pHelp->keyword ) )
return pHelp;
}
return NULL;
}
/*
* Now this is cleaner
*/
void do_help( CHAR_DATA *ch, char *argument )
{
HELP_DATA *pHelp;
if ( (pHelp = get_help( ch, argument )) == NULL )
{
send_to_char( "No help on that word.\n\r", ch );
return;
}
if ( pHelp->level >= 0 && str_cmp( argument, "imotd" ) )
{
stc( pHelp->keyword, ch );
stc( "\n\r", ch );
}
/*
* Strip leading '.' to allow initial blanks.
*/
if( !str_cmp(argument,"MXP_DEF") && !IS_MXP(ch) )
{
stc("This file can only be viewed by clients with MXP support. (Help MXP)\n\r",ch);
return;
}
if ( pHelp->text[0] == '.' )
stc( pHelp->text+1, ch );
else
stc( pHelp->text, ch );
return;
}
/*
* Help editor -Thoric
*/
void do_hedit( CHAR_DATA *ch, char *argument )
{
HELP_DATA *pHelp;
if ( !ch->desc )
{
send_to_char( "You have no descriptor.\n\r", ch );
return;
}
switch( ch->substate )
{
default:
break;
case SUB_HELP_EDIT:
if ( (pHelp = ch->dest_buf) == NULL )
{
bug( "hedit: sub_help_edit: NULL ch->dest_buf", 0 );
stop_editing( ch );
return;
}
STRFREE( pHelp->text );
pHelp->text = copy_buffer( ch );
stop_editing( ch );
return;
}
if ( (pHelp = get_help( ch, argument )) == NULL ) /* new help */
{
char argnew[MAX_INPUT_LENGTH];
int lev;
if ( isdigit(argument[0]) )
{
lev = number_argument( argument, argnew );
argument = argnew;
}
else
lev = get_trust(ch);
CREATE( pHelp, HELP_DATA, 1 );
pHelp->keyword = STRALLOC( strupper(argument) );
pHelp->text = STRALLOC( "" );
pHelp->level = lev;
add_help( pHelp );
}
ch->substate = SUB_HELP_EDIT;
ch->dest_buf = pHelp;
start_editing( ch, pHelp->text );
}
/*
* Stupid leading space muncher fix -Thoric
*/
char *help_fix( char *text )
{
char *fixed;
if ( !text )
return "";
fixed = strip_cr(text);
if ( fixed[0] == ' ' )
fixed[0] = '.';
return fixed;
}
void do_hset( CHAR_DATA *ch, char *argument )
{
HELP_DATA *pHelp;
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
smash_tilde( argument );
argument = one_argument( argument, arg1 );
if ( arg1[0] == '\0' )
{
send_to_char( "Syntax: hset <field> [value] [help page]\n\r", ch
);
send_to_char( "\n\r", ch
);
send_to_char( "Field being one of:\n\r", ch
);
send_to_char( " level keyword remove save\n\r", ch
);
return;
}
if ( !str_cmp( arg1, "save" ) )
{
FILE *fpout;
rename( "help.are", "help.are.bak" );
fclose( fpReserve );
if ( ( fpout = fopen( "help.are", "w" ) ) == NULL )
{
bug( "hset save: fopen", 0 );
perror( "help.are" );
fpReserve = fopen( NULL_FILE, "r" );
return;
}
fprintf( fpout, "#HELPS\n\n" );
for ( pHelp = first_help; pHelp; pHelp = pHelp->next )
fprintf( fpout, "%d %s~\n%s~\n\n",
pHelp->level, pHelp->keyword,
help_fix(pHelp->text) );
fprintf( fpout, "0 $~\n\n\n#$\n" );
fclose( fpout );
fpReserve = fopen( NULL_FILE, "r" );
send_to_char( "Saved.\n\r", ch );
return;
}
if ( str_cmp( arg1, "remove" ) )
argument = one_argument( argument, arg2 );
if ( (pHelp = get_help( ch, argument )) == NULL )
{
send_to_char( "Cannot find help on that subject.\n\r", ch );
return;
}
if ( !str_cmp( arg1, "remove" ) )
{
UNLINK( pHelp, first_help, last_help, next, prev );
STRFREE( pHelp->text );
STRFREE( pHelp->keyword );
DISPOSE( pHelp );
send_to_char( "Removed.\n\r", ch );
return;
}
if ( !str_cmp( arg1, "level" ) )
{
pHelp->level = atoi( arg2 );
send_to_char( "Done.\n\r", ch );
return;
}
if ( !str_cmp( arg1, "keyword" ) )
{
STRFREE( pHelp->keyword );
pHelp->keyword = STRALLOC( strupper(arg2) );
send_to_char( "Done.\n\r", ch );
return;
}
do_hset( ch, "" );
}
/*
* Show help topics in a level range -Thoric
* Idea suggested by Gorog
*/
void do_hlist( CHAR_DATA *ch, char *argument )
{
int min, max, minlimit, maxlimit, cnt;
char arg[MAX_INPUT_LENGTH];
char buf[MAX_STRING_LENGTH];
HELP_DATA *help;
maxlimit = get_trust(ch);
minlimit = maxlimit >= (MAX_LEVEL - 3) ? -1 : 0;
argument = one_argument( argument, arg );
if ( arg[0] != '\0' )
{
min = URANGE( minlimit, atoi(arg), maxlimit );
if ( argument[0] != '\0' )
max = URANGE( min, atoi(argument), maxlimit );
else
max = maxlimit;
}
else
{
min = minlimit;
max = maxlimit;
}
sprintf( buf, "Help Topics in level range %d to %d:\n\r\n\r", min, max
);
stc(buf,ch);
for ( cnt = 0, help = first_help; help; help = help->next )
if ( help->level >= min && help->level <= max )
{
sprintf( buf, " %3d %s\n\r", help->level, help->keyword );
stc(buf, ch);
++cnt;
}
if ( cnt )
{
sprintf( buf, "\n\r%d pages found.\n\r", cnt );
stc(buf,ch);
}
else
send_to_char( "None found.\n\r", ch );
}