/*___________________________________________________________________________*
)()( DalekenMUD 1.12 (C) 2000 )()(
`][' by Martin Thomson, Lee Brooks, `]['
|| Ken Herbert and David Jacques ||
|| ----------------------------------------------------------------- ||
|| Envy Diku Mud improvements copyright (C) 1994 by Michael Quan, ||
|| David Love, Guilherme 'Willie' Arnold, and Mitchell Tse. ||
|| Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael ||
|| Chastain, Michael Quan, and Mitchell Tse. ||
|| Original Diku Mud copyright (C) 1990, 1991 ||
|| by Sebastian Hammer, Michael Seifert, Hans Henrik St{rfeldt, ||
|| Tom Madsen, and Katja Nyboe. ||
|| ----------------------------------------------------------------- ||
|| Any use of this software must follow the licenses of the ||
|| creators. Much time and thought has gone into this software and ||
|| you are benefitting. We hope that you share your changes too. ||
|| What goes around, comes around. ||
|| ----------------------------------------------------------------- ||
|| mob_commands.c ||
|| Special commands for use in MUDPrograms. Based on N'Atas-ha's ||
|| MOBPrograms and SMAUG's MUDPrograms. ||
*_/<>\_________________________________________________________________/<>\_*/
#include "mud.h"
#include "event.h"
/*
* Local functions.
*/
void mp_force_sub args( ( CHAR_DATA *ch, const char *argument, bool quiet ) );
/*
* Display the MudPrograms and variables present.
*/
void append_progs( BUFFER *buf, MPROG_DATA *mprg, const char *argument,
MPROG_VAR *var )
{
int num = 0;
int argnum = -1;
bool sh = FALSE;
if( argument[0] != '\0' )
{
if( is_number( argument ) )
argnum = atoi( argument );
else if( !str_cmp( argument, "short" ) )
sh = TRUE;
else
sh = TRUE;
}
for( ; mprg; mprg = mprg->next, num++ )
{
if( argnum >= 0 && num != argnum )
continue;
bprintf( buf, "[%3d] %-20s", num,
flag_string( mud_prog_flags, &mprg->type ) );
bprintf( buf, "arg-[%s]\n\r", mprg->arglist );
if( sh )
continue;
bprintf( buf, "%s\n\r", mprg->comlist );
if( argnum >= 0 )
break;
}
num = 0;
for( ; argnum < 0 && var; var = var->next )
{
if( num++ == 0 )
buffer_strcat( buf, "Variables:\n\r" );
bprintf( buf, "%s = %s\n\r", var->name, var->value );
}
if( argnum >= 0 && !mprg )
{
buffer_clear( buf );
buffer_strcat( buf, "No such Program found.\n\r" );
}
}
void do_mpstat( CHAR_DATA *ch, const char *argument )
{
BUFFER *buf;
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
argument = one_argument( argument, arg );
if( arg[0] == '\0' )
{
send_to_char( "MobProg stat whom?\n\r", ch );
return;
}
if( ( victim = get_char_world( ch, arg ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
if( !IS_NPC( victim ) )
{
send_to_char( "Only Mobiles can have Programs!\n\r", ch );
return;
}
if( !( victim->pIndexData->mudprogs ) )
{
send_to_char( "That Mobile has no Programs set.\n\r", ch );
return;
}
buf = buffer_new( MAX_STRING_LENGTH );
bprintf( buf, "Name: %s. Vnum: %d.\n\r",
victim->name, victim->pIndexData->vnum );
bprintf( buf, "Short description: %s.\n\rLong description: %s",
victim->short_descr,
victim->long_descr[0] != '\0' ?
victim->long_descr : "(none).\n\r" );
bprintf( buf, "Hp: %d/%d. Mana: %d/%d. Move: %d/%d. \n\r",
victim->hit, victim->max_hit,
total_mana( victim->mana ), total_mana( victim->max_mana ),
victim->move, victim->max_move );
bprintf( buf, "Lv: %d. Class: %d. Align: %d. Gold: %d.\n\r",
victim->level, victim->class, victim->alignment,
victim->gold );
append_progs( buf, victim->pIndexData->mudprogs, argument,
victim->variables );
send_to_char( buf->data, ch );
buffer_free( buf );
return;
}
void do_opstat( CHAR_DATA *ch, const char *argument )
{
BUFFER *buf;
char arg[MAX_INPUT_LENGTH];
OBJ_DATA *obj;
argument = one_argument( argument, arg );
if( arg[0] == '\0' )
{
send_to_char( "ObjProg stat which?\n\r", ch );
return;
}
if( ( obj = get_obj_here( ch, arg ) ) == NULL )
{
send_to_char( "That isn't here.\n\r", ch );
return;
}
if( !( obj->pIndexData->mudprogs ) )
{
send_to_char( "That Object has no Programs set.\n\r", ch );
return;
}
buf = buffer_new( MAX_STRING_LENGTH );
bprintf( buf, "Name: %s. Vnum: %d. Level: %d.\n\r",
obj->name, obj->pIndexData->vnum, obj->level );
bprintf( buf, "Short description: %s.\n\r",
obj->short_descr );
append_progs( buf, obj->pIndexData->mudprogs, argument,
obj->variables );
send_to_char( buf->data, ch );
buffer_free( buf );
return;
}
void do_rpstat( CHAR_DATA *ch, const char *argument )
{
BUFFER *buf;
ROOM_INDEX_DATA *room;
room = ch->in_room;
if( !( room->mudprogs ) )
{
send_to_char( "This room has no Programs set.\n\r", ch );
return;
}
buf = buffer_new( MAX_STRING_LENGTH );
bprintf( buf, "Name: %s. Vnum: %d.\n\r", room->name, room->vnum );
append_progs( buf, room->mudprogs, argument, room->variables );
send_to_char( buf->data, ch );
buffer_free( buf );
return;
}
/*
* This command allows access to all the funky commands in this file
* through the mudprog interpreter. It is important to note that the
* check against players using this is on descriptor. This has the
* benefit of allowing mobprograms, through mp_qforce, make players run
* these commands, huge flexibility advantages, no loopholes forseen, yet!
*
* However,
* Utmost care at all times please. --Symposium
*/
void do_mpcomm( CHAR_DATA *ch, const char *argument )
{
if( ch->desc )
{
send_to_char( "You commune with the mobiles, how boring.\n\r", ch );
return;
}
if( !prog_only_cmnd( ch, argument ) )
progbug( ch, "bad mpcommand" );
return;
}
/* prints the message to the room at large */
void mp_aecho( CHAR_DATA *ch, const char *argument )
{
DESCRIPTOR_DATA *d;
if( argument[0] == '\0' )
{
progbug( ch, "aecho - called w/o argument." );
return;
}
for( d = descriptor_list; d; d = d->next )
{
if( !IS_SET( d->interpreter->flags, INTERPRETER_NOMESSAGE )
&& ch->in_room->area == d->character->in_room->area
&& IS_AWAKE( d->character ) )
act( argument, ch, NULL, d->character, TO_VICT );
}
return;
}
/* prints the argument to all the rooms aroud the mobile */
void mp_asound( CHAR_DATA *ch, const char *argument )
{
ROOM_INDEX_DATA *was_in_room;
int door;
if( argument[0] == '\0' )
{
progbug( ch, "Mpasound - No argument." );
return;
}
was_in_room = ch->in_room;
for( door = 0; door <= 5; door++ )
{
EXIT_DATA *pexit;
if( ( pexit = was_in_room->exit[door] ) != NULL
&& pexit->to_room != NULL
&& pexit->to_room != was_in_room )
{
ch->in_room = pexit->to_room;
REMOVE_BIT( SysInfo->flags, SYSINFO_ACT_TRIGGER );
act( argument, ch, NULL, NULL, TO_ROOM );
}
}
ch->in_room = was_in_room;
return;
}
/* Lets the mobile do a command at another location. Very useful */
void mp_at( CHAR_DATA *ch, const char *argument )
{
char arg[MAX_INPUT_LENGTH];
ROOM_INDEX_DATA *location;
ROOM_INDEX_DATA *original;
OBJ_DATA *orig_on;
CHAR_DATA *wch;
argument = one_argument( argument, arg );
if( arg[0] == '\0' || argument[0] == '\0' )
{
progbug( ch, "Mpat - Bad argument: %s %s.", arg, argument );
return;
}
if( ( location = find_location( ch, arg ) ) == NULL )
{
progbug( ch, "Mpat - No such location: %s.", arg );
return;
}
original = ch->in_room;
orig_on = ch->on;
char_from_room( ch );
char_to_room( ch, location );
if( !prog_only_cmnd( ch, argument ) )
interpret( ch, argument );
/*
* See if 'ch' still exists before continuing!
* Handles 'at XXXX quit' case.
*/
for( wch = char_list; wch != NULL; wch = wch->next )
{
if( wch == ch && !wch->deleted )
{
char_from_room( ch );
char_to_room( ch, original );
ch->on = orig_on;
break;
}
}
return;
}
/* Hides the mobile quite effectively, mobile only */
void mp_burrow( CHAR_DATA *ch, const char *argument )
{
if( IS_NPC( ch ) )
xSET_BIT( ch->act, ACT_BURIED );
}
void mp_damage( CHAR_DATA *ch, const char *argument )
{
char buf[MAX_INPUT_LENGTH];
char arg1[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
CHAR_DATA *nextinroom;
int dam;
int already_fighting = FALSE;
argument = one_argument( argument, arg1 );
if ( !str_cmp( arg1, "all" ) )
{
for( victim = ch->in_room->people; victim; victim = nextinroom )
{
nextinroom = victim->next_in_room;
if( victim != ch && can_see( ch, victim ) )
{
sprintf( buf, "'%s' %s", name_expand( arg1, victim ),
argument );
mp_damage( ch, buf );
}
}
return;
}
if( argument[0] == '\0' )
{
progbug( ch, "Mpdamage: no damage amount given." );
return;
}
if( ( victim = get_char_room( ch, arg1 ) ) == NULL )
{
progbug( ch, "Mpdamage: victim not in room." );
return;
}
if( victim == ch )
{
progbug( ch, "Mpdamage: trying to damage self." );
return;
}
dam = atoi( argument );
if( ( dam < 0) || ( dam > 32000 ) )
{
progbug( ch, "Mpdamage: invalid (nonexistent?) argument: %s" );
return;
}
if( ch->fighting )
already_fighting = TRUE;
damage( ch, victim, dam, TYPE_MPDAMAGE, WEAR_NONE );
if( already_fighting )
stop_fighting( ch, TRUE );
return;
}
/*
* Either lag PC characters (not all that useful).
* or delay an NPC that will allow it to trigger a delay_prog.
*/
void mp_delay( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *victim;
char arg[MAX_INPUT_LENGTH];
int val;
EVENT *e;
argument = one_argument( argument, arg );
if( !*arg )
victim = ch;
else if( !( victim = get_char_world( ch, arg ) ) )
return;
val = atoi( argument );
if( val < 0 )
{
progbug( ch, "Bad mp_delay argument: %s %s.", arg, argument );
return;
}
if( IS_NPC( victim ) )
{
if( victim->pIndexData->vnum == MOB_VNUM_SUPERMOB )
{
progbug( ch, "Trying to delay supermob.", arg, argument );
return;
}
if( xIS_SET( victim->pIndexData->progtypes, DELAY_PROG ) )
{
e = create_char_event( victim, evn_prog_trigger,
val );
e->data[0] = DELAY_PROG;
}
}
victim->wait = val;
return;
}
/*
* Deposit some gold into the current area's economy -Thoric
*/
void mp_deposit( CHAR_DATA *ch, const char *argument )
{
int gold;
if( argument[0] == '\0' )
{
progbug( ch, "deposit - bad syntax" );
return;
}
gold = atoi( argument );
if( gold <= ch->gold && ch->in_room )
{
ch->gold -= gold;
ch->in_room->area->economy += gold;
}
}
/*
* Withdraw some gold from the current area's economy -Thoric
*/
void mp_withdraw( CHAR_DATA *ch, const char *argument )
{
int gold;
if( argument[0] == '\0' )
{
progbug( ch, "withdraw - bad syntax" );
return;
}
gold = atoi( argument );
if( ch->gold < 1000000000 && gold < 1000000000 && ch->in_room
&& ch->in_room->area->economy >= gold )
{
ch->gold += gold;
ch->in_room->area -= gold;
}
}
void mp_dream( CHAR_DATA *ch, const char *argument )
{
char arg1[MAX_STRING_LENGTH];
CHAR_DATA *vict;
argument = one_argument( argument, arg1 );
if( ( vict = get_char_world( ch, arg1 ) ) == NULL )
{
progbug( ch, "Mpdream: No such character" );
return;
}
if( vict->position <= POS_SLEEPING )
{
send_to_char( argument, vict );
send_to_char( "\n\r", vict );
}
return;
}
/* prints the message to the room at large */
void mp_echo( CHAR_DATA *ch, const char *argument )
{
if( argument[0] == '\0' )
{
progbug( ch, "echo - called w/o argument." );
return;
}
act( argument, ch, NULL, NULL, TO_ROOM );
return;
}
/* prints the message to everyone in the room other than the mob and victim */
void mp_echoaround( CHAR_DATA *ch, const char *argument )
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
argument = one_argument( argument, arg );
if( arg[0] == '\0' )
{
progbug( ch, "echoaround - No argument." );
return;
}
if( !( victim = get_char_room( ch, arg ) ) )
{
progbug( ch, "echoaround - victim does not exist: %s.", arg );
return;
}
act( argument, ch, NULL, victim, TO_NOTVICT );
return;
}
/* prints the message to only the victim */
void mp_echoat( CHAR_DATA *ch, const char *argument )
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
argument = one_argument( argument, arg );
if( arg[0] == '\0' || argument[0] == '\0' )
{
progbug( ch, "echoat - No argument." );
return;
}
if( !( victim = get_char_room( ch, arg ) ) )
{
progbug( ch, "echoat - victim does not exist: %s.", arg );
return;
}
act( argument, ch, NULL, victim, TO_VICT );
return;
}
void mp_force_sub( CHAR_DATA *ch, const char *argument, bool quiet )
{
char arg[MAX_INPUT_LENGTH];
DESCRIPTOR_DATA *d;
argument = one_argument( argument, arg );
if( arg[0] == '\0' || argument[0] == '\0' )
{
progbug( ch, "Mp[q]force - Bad syntax: %s %s.",arg, argument );
return;
}
if( !str_cmp( arg, "all" ) )
{
CHAR_DATA *vch;
CHAR_DATA *vch_next;
for( vch = char_list; vch != NULL; vch = vch_next )
{
vch_next = vch->next;
if( vch->in_room == ch->in_room
&& get_trust( vch ) < get_trust( ch )
&& can_see( ch, vch ) )
{
d = vch->desc;
if( quiet )
vch->desc = NULL;
if( !quiet || !prog_only_cmnd( vch, argument ) )
interpret( vch, argument );
vch->desc = d;
}
}
}
else
{
CHAR_DATA *victim;
if( ( victim = get_char_room( ch, arg ) ) == NULL )
{
progbug( ch, "Mp[q]force - No such victim." );
return;
}
if( victim == ch )
{
progbug( ch, "Mp[q]force - Forcing oneself." );
return;
}
d = victim->desc;
if( quiet )
victim->desc = NULL;
if( !quiet || !prog_only_cmnd( victim, argument ) )
interpret( victim, argument );
victim->desc = d;
}
return;
}
/*
* Lets the mobile force someone to do something. Must be mortal level
* and the all argument only affects those in the room with the mobile.
*
* Note: additionally this force command allows the character access to
* the extra commands commands in this file, either through mp_comm or
* directly.
* --Symposium
*/
void mp_qforce( CHAR_DATA *ch, const char *argument )
{
mp_force_sub( ch, argument, TRUE );
}
/* Standard force, no tricks allowed */
void mp_force( CHAR_DATA *ch, const char *argument )
{
mp_force_sub( ch, argument, FALSE );
}
/* Lets the mobile goto any location it wishes that is not private */
void mp_goto( CHAR_DATA *ch, const char *argument )
{
char arg[MAX_INPUT_LENGTH];
ROOM_INDEX_DATA *location;
one_argument( argument, arg );
if( arg[0] == '\0' )
{
progbug( ch, "Mpgoto - No argument." );
return;
}
if( ( location = find_location( ch, arg ) ) == NULL )
{
progbug( ch, "Mpgoto - No such location: %s.", arg );
return;
}
if( ch->fighting != NULL )
stop_fighting( ch, TRUE );
char_from_room( ch );
char_to_room( ch, location );
return;
}
void mp_grant( CHAR_DATA *ch, const char *argument )
{
char arg1[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
int num;
argument = one_argument( argument, arg1 );
if( argument[0] == '\0' || !is_number( argument ) )
{
progbug( ch, "grant: called with no arguments" );
return;
}
if( !( victim = get_char_world( ch, arg1 ) ) )
{
progbug( ch, "grant: can't find player to grant." );
return;
}
num = atoi_special( argument ) * 100;
sprintf( arg1, "%s has granted you %d experience!\n\r",
ch->name, num / 100 );
wiznetf( ch, WIZ_LEVELS, get_trust( ch ),
"%s has just granted %s %d experience (mp_grant).",
ch->name, victim->name, num / 100 );
send_to_char( arg1, victim );
gain_exp( victim, num );
return;
}
/* lets the mobile destroy an object in its inventory
it can also destroy a worn object and it can destroy
items using all.xxxxx or just plain all of them */
void mp_junk( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
OBJ_DATA *obj_next;
if( argument[0] == '\0' )
{
progbug( ch, "Mpjunk - No argument." );
return;
}
if( str_cmp( argument, "all" ) && str_prefix( "all.", argument ) )
{
if( ( obj = get_obj_wear( ch, argument ) ) != NULL )
{
unequip_char( ch, obj );
extract_obj( obj );
return;
}
if( ( obj = get_obj_carry( ch, argument ) ) == NULL )
return;
extract_obj( obj );
}
else
for( obj = ch->carrying; obj != NULL; obj = obj_next )
{
obj_next = obj->next_content;
if( argument[3] == '\0' || is_obj_name( obj, &argument[4] ) )
{
if( obj->wear_loc != WEAR_NONE )
unequip_char( ch, obj );
extract_obj( obj );
}
}
return;
}
/* lets the mobile kill any player or mobile without murder */
void mp_kill( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *victim;
if( argument[0] == '\0' )
{
progbug( ch, "MpKill - no argument." );
return;
}
if( ( victim = get_char_room( ch, argument ) ) == NULL )
{
progbug( ch, "MpKill - Victim not in room: %s.", argument );
return;
}
if( victim == ch )
{
progbug( ch, "MpKill - Bad victim to attack, self." );
return;
}
if( IS_AFFECTED( ch, AFF_CHARM ) && ch->master == victim )
{
progbug( ch, "MpKill - Charmed mob attacking master: %s.",
ch->master->name );
return;
}
if( ch->position == POS_FIGHTING )
{
progbug( ch, "MpKill - Already fighting." );
return;
}
multi_hit( ch, victim, TYPE_UNDEFINED );
return;
}
/* lets the mobile load an item or mobile. All items
are loaded into inventory. you can specify a level with
the load object portion as well. */
void mp_mload( CHAR_DATA *ch, const char *argument )
{
char arg[MAX_INPUT_LENGTH];
MOB_INDEX_DATA *pMobIndex;
CHAR_DATA *victim;
one_argument( argument, arg );
if( arg[0] == '\0' || !is_number( arg ) )
{
progbug( ch, "Mpmload - Bad vnum as arg: %s.", arg );
return;
}
if( ( pMobIndex = get_mob_index( atoi( arg ) ) ) == NULL )
{
progbug( ch, "Mpmload - Bad mob vnum: %s.", arg );
return;
}
victim = create_mobile( pMobIndex );
char_to_room( victim, ch->in_room );
return;
}
/*
* Trimmed down version of mset.
*/
void mp_mset( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *vict;
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
char arg3[MAX_INPUT_LENGTH];
int value;
int *ival = NULL;
char **sval = NULL;
argument = one_argument( argument, arg1 );
argument = one_argument( argument, arg2 );
strcpy( arg3, argument );
if( !( vict = get_char_world( ch, arg1 ) ) )
{
progbug( ch, "mset: non-existant character %s.", arg1 );
return;
}
value = atoi_functions( arg3 );
if( !str_cmp( arg2, "short" ) )
sval = &vict->short_descr;
else if( !str_cmp( arg2, "long" ) )
{
strcat( arg3, "\n\r" );
sval = &vict->long_descr;
}
else if( !str_cmp( arg2, "title" ) )
{
set_title( vict, arg3 );
return;
}
else if( !str_cmp( arg2, "class" ) )
{
if( value < 0 || value >= MAX_CLASS )
{
for( value = 0; value < MAX_CLASS; value++ )
{
if( !str_cmp( arg3, class_table[value].who_name )
|| !str_cmp( arg3, class_table[value].name ) )
break;
}
if( value >= MAX_CLASS )
{
progbug( ch, "mset: invalid class." );
return;
}
vict->class = value;
return;
}
if( value == -1 && !IS_NPC( ch ) )
{
progbug( ch, "mset: invalid class 'none' on a PC." );
return;
}
vict->class = value;
return;
}
else if( !str_cmp( arg2, "sex" ) )
{
if( IS_AFFECTED( vict, AFF_POLYMORPH ) )
return;
if( value < 0 || value > 2 )
{
if( !str_cmp( arg3, "male" ) )
vict->sex = SEX_MALE;
else if( !str_cmp( arg3, "female" ) )
vict->sex = SEX_FEMALE;
else if( !str_cmp( arg3, "neuter" ) )
vict->sex = SEX_NEUTRAL;
else
progbug( ch, "mset: invalid sex." );
return;
}
vict->sex = value;
return;
}
else if( !str_cmp( arg2, "race" ) )
{
if( IS_AFFECTED( vict, AFF_POLYMORPH ) )
return;
value = race_lookup( arg3 );
if( value < 0 )
{
progbug( ch, "mset: invalid race." );
return;
}
vict->race = value;
return;
}
else if( !str_cmp( arg2, "sublevel" ) )
{
if( value < 0 || value > vict->level )
{
progbug( ch, "mset: sublevel out of range." );
return;
}
vict->sublevel = value;
return;
}
else if( !str_cmp( arg2, "gold" ) )
ival = &vict->gold;
else if( !str_cmp( arg2, "hp" ) )
ival = &vict->hit;
else if( !str_cmp( arg2, "maxhp" ) )
ival = &vict->max_hit;
else if( !str_prefix( "mana", arg2 ) || !str_prefix( "maxmana", arg2 ) )
{
int which;
argument = &arg2[4];
if( !str_prefix( "max", arg2 ) )
argument += 3;
while( isspace( *argument ) )
argument++;
if( !str_cmp( argument, "air" ) )
which = MAGIC_AIR;
else if( !str_cmp( argument, "earth" ) )
which = MAGIC_EARTH;
else if( !str_cmp( argument, "fire" ) )
which = MAGIC_FIRE;
else if( !str_cmp( argument, "spirit" ) )
which = MAGIC_SPIRIT;
else if( !str_cmp( argument, "water" ) )
which = MAGIC_WATER;
else
{
progbug( ch, "mset: bad magic sphere." );
return;
}
if( !str_prefix( "max", arg2 ) )
ival = &vict->max_mana[which];
else
ival = &vict->mana[which];
}
else if( !str_cmp( arg2, "move" ) )
ival = &vict->move;
else if( !str_cmp( arg2, "maxmove" ) )
ival = &vict->max_move;
else if( !str_cmp( arg2, "practice" ) )
ival = &vict->practice;
else if( !str_cmp( arg2, "align" ) )
{
if( value < -1000 || value > 1000 )
return;
ival = &vict->alignment;
}
if( !IS_NPC( vict ) )
{
if( !str_cmp( arg2, "name" ) )
sval = &vict->name;
else if( !str_cmp( arg2, "str" ) )
ival = &vict->pcdata->perm_str;
else if( !str_cmp( arg2, "int" ) )
ival = &vict->pcdata->perm_int;
else if( !str_cmp( arg2, "wis" ) )
ival = &vict->pcdata->perm_wis;
else if( !str_cmp( arg2, "dex" ) )
ival = &vict->pcdata->perm_dex;
else if( !str_cmp( arg2, "con" ) )
ival = &vict->pcdata->perm_con;
else if( !str_cmp( arg2, "multi" ) )
{
char classbuf[ MAX_INPUT_LENGTH ];
if( !str_cmp( argument, "all clear" ) )
{
vict->class = get_first_class( vict );
for( value = 0; value < AVAIL_CLASS; value++ )
vict->pcdata->multi_class[value] = CLASS_UNKNOWN;
return;
}
argument = one_argument( argument, classbuf );
for( value = 0; value < AVAIL_CLASS; value++ )
if( !str_cmp( classbuf, class_table[value].who_name )
|| !str_cmp( classbuf, class_table[value].name ) )
break;
if( value >= AVAIL_CLASS )
{
progbug( ch, "mset multi: bad class name %s", classbuf );
return;
}
if( !str_cmp( argument, "clear" ) )
{
if( vict->pcdata->multi_class[value] > CLASS_ADEPT )
{
progbug( ch, "mset multi clear: bad args" );
return;
}
vict->pcdata->multi_class[value] = CLASS_UNKNOWN;
if( vict->sublevel )
vict->sublevel = 0;
return;
}
if( !str_cmp( argument, "aspire" ) )
{
if( get_aspire_class( vict ) >= 0 )
{
progbug( ch, "mset multi aspire: bad args" );
return;
}
vict->pcdata->multi_class[value] = CLASS_ASPIRING;
return;
}
if( !str_cmp( argument, "adept" ) )
{
if( vict->pcdata->multi_class[value] > CLASS_ADEPT )
{
progbug( ch, "mset multi adept: bad args" );
return;
}
vict->pcdata->multi_class[value] = CLASS_ADEPT;
return;
}
progbug( ch, "mset multi: bad args" );
return;
}
else if( !str_cmp( arg2, "qscore" ) )
ival = &vict->pcdata->quest->score;
else if( !str_cmp( arg2, "qtime" ) )
ival = &vict->pcdata->quest->time;
else if( !str_prefix( "magic", arg2 ) )
{
int which;
argument = &arg2[4];
while( isspace( *argument ) )
argument++;
if( !str_cmp( argument, "air" ) )
which = MAGIC_AIR;
else if( !str_cmp( argument, "earth" ) )
which = MAGIC_EARTH;
else if( !str_cmp( argument, "fire" ) )
which = MAGIC_FIRE;
else if( !str_cmp( argument, "spirit" ) )
which = MAGIC_SPIRIT;
else if( !str_cmp( argument, "water" ) )
which = MAGIC_WATER;
else
{
progbug( ch, "mset magic: bad magic sphere." );
return;
}
ival = &vict->pcdata->perm_magic[which];
}
else if( !str_cmp( arg2, "thirst" ) )
{
strcat( arg3, "0" );
ival = &vict->pcdata->condition[COND_THIRST];
}
else if( !str_cmp( arg2, "full" ) )
{
strcat( arg3, "0" );
ival = &vict->pcdata->condition[COND_FULL];
}
else if( !str_cmp( arg2, "drunk" ) )
{
strcat( arg3, "0" );
ival = &vict->pcdata->condition[COND_DRUNK];
}
else if( !str_cmp( arg2, "clan" ) )
{
CLAN_DATA *clan;
if( !str_cmp( arg3, "none" ) )
{
if( is_clan( vict ) )
remove_from_clan( vict );
return;
}
if( !( clan = clan_lookup( arg3 ) ) )
{
progbug( ch, "mset clan: non-existant clan." );
return;
}
if( vict->pcdata->clan == clan )
return;
if( is_clan( vict ) )
remove_from_clan( vict );
add_to_clan( vict, clan, RANK_CLANSMAN );
return;
}
else if( !str_cmp( arg2, "religion" ) )
{
RELIGION_DATA *religion;
if ( !( religion = religion_lookup( arg3 ) ) )
{
progbug( ch, "mset religion: invalid religion." );
return;
}
vict->pcdata->religion = religion;
return;
}
else if( !str_cmp( arg2, "clanrank" ) )
{
CLAN_DATA *clan;
if( !( clan = vict->pcdata->clan ) )
{
progbug( ch, "mset clanrank: vict not in clan." );
return;
}
if( value < RANK_EXILED )
{
remove_from_clan( vict );
return;
}
if( value > RANK_OVERLORD )
{
progbug( ch, "mset clanrank: bad clan rank %d.", value );
return;
}
if( vict->pcdata->clan_rank == value )
return;
switch( value )
{
default:
break;
case RANK_CLANHERO:
if( clan->clanheros >= clan->members / 3 )
{
progbug( ch, "mset clanrank: too many heroes." );
return;
}
break;
case RANK_CHIEFTAIN:
if( clan->members < 10 )
{
progbug( ch, "mset clanrank: too many cheiftans." );
return;
}
break;
case RANK_OVERLORD:
if( clan->overlord != NULL && clan->overlord[0] != '\0' )
{
progbug( ch, "mest clanrank: already an overlord." );
return;
}
break;
}
remove_from_clan( vict );
add_to_clan( vict, clan, value );
return;
}
}
else /* IS_NPC(vict) */
{
if( !str_cmp( arg2, "name" ) )
sval = &vict->name;
else if( !str_cmp( arg2, "level" ) )
ival = &vict->level;
else if( !str_cmp( arg2, "spec" ) )
{
if( ( value = spec_lookup( arg3 ) ) <= 0 )
{
progbug( ch, "mset spec: invalid spec_fun name" );
return;
}
ival = &vict->spec_fun;
}
}
if( ival )
*ival = atoi_functions( arg3 );
else if( sval )
{
free_string( *sval );
*sval = str_dup( arg3 );
}
else
{
progbug( ch, "mset: unknown field %s.", arg2 );
return;
}
return;
}
void mp_oload( CHAR_DATA *ch, const char *argument )
{
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
OBJ_INDEX_DATA *pObjIndex;
OBJ_DATA *obj;
int level;
argument = one_argument( argument, arg1 );
argument = one_argument( argument, arg2 );
if( arg1[0] == '\0' || !is_number( arg1 ) )
{
progbug( ch, "Mpoload - Bad syntax: %s %s %s.",
arg1, arg2, argument );
return;
}
if( arg2[0] == '\0' )
{
level = 0;
}
else
{
/*
* New feature from Alander.
*/
if( !is_number( arg2 ) )
{
progbug( ch, "Mpoload - Bad syntax: arg2: %s.", arg2 );
return;
}
level = atoi( arg2 );
if( level < 0 || level > get_trust( ch ) )
{
progbug( ch, "Mpoload - Bad level: %s.", arg2 );
return;
}
}
if( ( pObjIndex = get_obj_index( atoi( arg1 ) ) ) == NULL )
{
progbug( ch, "Mpoload - Bad vnum arg: %s.", arg1 );
return;
}
obj = create_object( pObjIndex, level );
if( CAN_WEAR( obj, ITEM_TAKE ) )
{
obj_to_char( obj, ch );
}
else
{
obj_to_room( obj, ch->in_room );
}
return;
}
/*
* Trimmed down version of oset.
*/
void mp_oset( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
char arg3[MAX_INPUT_LENGTH];
int value;
int *ival = NULL;
char **sval = NULL;
argument = one_argument( argument, arg1 );
argument = one_argument( argument, arg2 );
strcpy( arg3, argument );
if( !( obj = get_obj_here( ch, arg1 ) ) )
{
progbug( ch, "oset: non-existant object %s.", arg1 );
return;
}
value = atoi_functions( arg3 );
if( !str_cmp( arg2, "name" ) )
sval = &obj->name;
else if( !str_cmp( arg2, "short" ) )
sval = &obj->short_descr;
else if( !str_cmp( arg2, "long" ) )
{
strcat( arg3, "\n\r" );
sval = &obj->description;
}
else if( !str_cmp( arg2, "action" ) )
{
strcat( arg3, "\n\r" );
sval = &obj->action;
}
else if( !str_cmp( arg2, "value0" ) || !str_cmp( arg2, "v0" ) )
ival = &obj->value[0];
else if( !str_cmp( arg2, "value1" ) || !str_cmp( arg2, "v1" ) )
ival = &obj->value[2];
else if( !str_cmp( arg2, "value2" ) || !str_cmp( arg2, "v2" ) )
ival = &obj->value[2];
else if( !str_cmp( arg2, "value3" ) || !str_cmp( arg2, "v3" ) )
ival = &obj->value[3];
else if( !str_cmp( arg2, "extra" ) )
ival = &obj->extra_flags;
else if( !str_cmp( arg2, "wear" ) )
ival = &obj->wear_flags;
else if( !str_cmp( arg2, "level" ) )
ival = &obj->level;
else if( !str_cmp( arg2, "weight" ) )
ival = &obj->weight; /* be careful! no checks! */
else if( !str_cmp( arg2, "cost" ) )
ival = &obj->cost;
else if( !str_cmp( arg2, "timer" ) )
{
set_timer_tick( obj, value );
return;
}
else if( !str_cmp( arg2, "imptimer" ) )
{
create_obj_event( obj, evn_imp_grab, value * PULSE_TICK );
return;
}
else if( !str_cmp( arg2, "required" ) )
{
obj->required_skill = skill_lookup( arg3 );
return;
}
else if( !str_cmp( arg2, "condition" ) )
{
value *= 10;
ival = &obj->condition;
}
if( ival )
*ival = value;
else if( sval )
{
free_string( *sval );
*sval = str_dup( arg3 );
}
else
{
progbug( ch, "oset: unknown field %s.", arg2 );
return;
}
return;
}
/*
* openpassage <#fromvnum> <#tovnum> <dir>
* only a one directional passage, <dir> can be number/n/s/e...
*
* Potential Problem: these might not be able to be removed by progs
* in rooms which have exit randomisations. --Symposium
*/
void mp_openpassage( CHAR_DATA *ch, const char *argument )
{
char arg1[ MAX_INPUT_LENGTH ];
char arg2[ MAX_INPUT_LENGTH ];
ROOM_INDEX_DATA *targetRoom, *fromRoom;
int targetRoomVnum, fromRoomVnum, exit_num;
argument = one_argument( argument, arg1 );
argument = one_argument( argument, arg2 );
if( arg1[0] == '\0' || arg2[0] == '\0' || argument[0] == '\0' )
{
progbug( ch, "Mpopenpassage - Bad syntax '%s' '%s' %s",
arg1, arg2, argument );
return;
}
if( !is_number( arg1 ) || !is_number( arg2 ) )
{
progbug( ch, "MpOpenPassage - Bad syntax: %s %s ...", arg1, arg2 );
return;
}
fromRoomVnum = atoi( arg1 );
targetRoomVnum = atoi( arg2 );
if( ( fromRoom = get_room_index( fromRoomVnum ) ) == NULL
|| ( targetRoom = get_room_index( targetRoomVnum ) ) == NULL )
{
progbug( ch, "MpOpenPassage - Bad room vnums: %d - %d",
fromRoomVnum, targetRoomVnum );
return;
}
if( isdigit( argument[0] ) )
{
exit_num = argument[0] - '0';
}
else switch( argument[0] )
{
case 'n': case 'N':
exit_num = 0; break;
case 'e': case 'E':
exit_num = 1; break;
case 's': case 'S':
exit_num = 2; break;
case 'w': case 'W':
exit_num = 3; break;
case 'u': case 'U':
exit_num = 4; break;
case 'd': case 'D':
exit_num = 5; break;
default:
progbug( ch, "mpopenpassage: Bad direction." );
return;
}
if( exit_num < 0 || exit_num >= MAX_DIR )
{
progbug( ch, "mpopenpassage: invalid exit number %d.", exit_num );
return;
}
if( fromRoom->exit[exit_num] != NULL )
{
if( !IS_SET( fromRoom->exit[exit_num]->exit_info, EX_TEMPORARY ) )
progbug( ch, "MpOpenPassage - Exit exists" );
return;
}
fromRoom->exit[exit_num] = new_exit( );
fromRoom->exit[exit_num]->in_room = fromRoom;
fromRoom->exit[exit_num]->to_room = targetRoom;
fromRoom->exit[exit_num]->key = -1;
SET_BIT( fromRoom->exit[exit_num]->exit_info, EX_TEMPORARY );
SET_BIT( fromRoom->exit[exit_num]->rs_flags, EX_TEMPORARY );
}
/*
* closepassage <#room> <dir>
* as above (SEE NOTE)
*/
void mp_closepassage( CHAR_DATA *ch, const char *argument )
{
char arg[MAX_INPUT_LENGTH];
ROOM_INDEX_DATA *room;
int exit_num;
argument = one_argument( argument, arg );
if( arg[0] == '\0' || argument[0] == '\0' )
{
progbug( ch, "mp_close_passage: illegal arguments: %s %s",
arg, argument );
return;
}
if( ( room = get_room_index( atoi( arg ) ) ) == NULL )
{
progbug( ch, "mp_close_passage: couldn't find room '%s'!", arg );
return;
}
if( isdigit( argument[0] ) )
{
exit_num = argument[0] - '0';
}
else switch( argument[0] )
{
case 'n': case 'N':
exit_num = 0; break;
case 'e': case 'E':
exit_num = 1; break;
case 's': case 'S':
exit_num = 2; break;
case 'w': case 'W':
exit_num = 3; break;
case 'u': case 'U':
exit_num = 4; break;
case 'd': case 'D':
exit_num = 5; break;
default:
progbug( ch, "mpclosepassage: Bad direction." );
return;
}
if( exit_num < 0 || exit_num > MAX_DIR || !room->exit[exit_num]
|| !IS_SET( room->exit[exit_num]->rs_flags
| room->exit[exit_num]->exit_info, EX_TEMPORARY ) )
{
progbug( ch, "mpclosepassage: exit %d from %d isn't temporary.",
exit_num, room->vnum );
return;
}
free_exit( room->exit[exit_num] );
room->exit[exit_num] = NULL;
return;
}
/*
* Stop fights in the room.
*/
void mp_peace( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *rch;
for( rch = ch->in_room->people; rch; rch = rch->next_in_room )
{
if( rch->fighting )
stop_fighting( rch, TRUE );
}
send_to_char( "Ok.\n\r", ch );
return;
}
/* Lets the mobile purge all objects and other npcs in the room,
or purge a specified object or mob in the room. It can purge
itself, but this had best be the last command in the MOBprogram
otherwise ugly stuff will happen */
void mp_purge( CHAR_DATA *ch, const char *argument )
{
purge_room( ch, argument );
return;
}
/*
* Set a 'prog variable.
*/
void mp_set( CHAR_DATA *ch, const char *argument )
{
char var[MAX_INPUT_LENGTH];
argument = first_arg( argument, var, FALSE );
set_mob_var( ch, var, argument );
}
/*
* Delete/remove a 'prog variable.
*/
void mp_delete( CHAR_DATA *ch, const char *argument )
{
delete_mob_var( ch, argument );
}
/* Lets the mobile transfer people. The all argument transfers
everyone in the current room to the specified location. */
void mp_transfer( CHAR_DATA *ch, const char *argument )
{
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
ROOM_INDEX_DATA *location;
DESCRIPTOR_DATA *d;
CHAR_DATA *victim;
argument = one_argument( argument, arg1 );
argument = one_argument( argument, arg2 );
if( arg1[0] == '\0' )
{
progbug( ch, "Mptransfer - Bad syntax: %s %s %s.",
arg1, arg2, argument );
return;
}
if( !str_cmp( arg1, "all" ) )
{
for( d = descriptor_list; d != NULL; d = d->next )
{
if( !IS_SET( d->interpreter->flags, INTERPRETER_SAFE )
&& d->character != ch
&& d->character->in_room != NULL
&& can_see( ch, d->character ) )
{
char buf[MAX_STRING_LENGTH];
sprintf( buf, "%s %s", d->character->name, arg2 );
do_transfer( ch, buf );
}
}
return;
}
/*
* Thanks to Grodyn for the optional location parameter.
*/
if( arg2[0] == '\0' )
{
location = ch->in_room;
}
else
{
if( ( location = find_location( ch, arg2 ) ) == NULL )
{
progbug( ch, "Mptransfer - No such location: %s.", arg2 );
return;
}
if( room_is_private( location ) )
{
progbug( ch, "Mptransfer - Private room: vnum %d.",
location->vnum );
return;
}
}
if( ( victim = get_char_world( ch, arg1 ) ) == NULL )
{
progbug( ch, "Mptransfer - No such person %s.", arg1 );
return;
}
if( victim->in_room == NULL )
{
progbug( ch, "Mptransfer - Victim in Limbo." );
return;
}
if( victim->fighting != NULL )
stop_fighting( victim, TRUE );
char_from_room( victim );
char_to_room( victim, location );
return;
}
/* Lets the mobile transfer objects.
* Use otransfer <object> character <character>
* otransfer <object> object <object>
* otransfer <object> [room] <room>
*/
void mp_otransfer( CHAR_DATA *ch, const char *argument )
{
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
ROOM_INDEX_DATA *location = NULL;
CHAR_DATA *vict = NULL;
OBJ_DATA *obj;
OBJ_DATA *objto = NULL;
argument = one_argument( argument, arg1 );
argument = one_argument( argument, arg2 );
if( arg1[0] == '\0' || arg2[0] == '\0' )
{
progbug( ch, "Otransfer - Bad syntax: %s %s %s.",
arg1, arg2, argument );
return;
}
if( ( obj = get_obj_here( ch, arg1 ) ) == NULL )
{
progbug( ch, "Otransfer - No such object %s.", arg1 );
return;
}
if( !str_prefix( arg2, "character" ) )
{
if( ( vict = get_char_world( ch, argument ) ) == NULL )
{
progbug( ch, "Otransfer - No such character: %s.", argument );
return;
}
}
else if( !str_prefix( arg2, "object" ) )
{
if( ( objto = get_obj_here( ch, argument ) ) == NULL )
{
progbug( ch, "Otransfer - No such object: %s.", argument );
return;
}
}
else if( !str_prefix( arg2, "room" ) )
strcpy( arg2, argument );
if( !vict && !objto
&& ( location = find_location( ch, arg2 ) ) == NULL )
{
progbug( ch, "Otransfer - No such location: %s.", arg2 );
return;
}
if( obj->in_room )
obj_from_room( obj );
else if( obj->in_obj )
obj_from_obj( obj );
else if( obj->carried_by )
obj_from_char( obj );
else
progbug( ch, "Otransfer - Obj [%s] not anywhere.", obj->name );
if( vict )
obj_to_char( obj, vict );
else if( objto )
obj_to_obj( obj, objto );
else if( location )
{
obj_to_room( obj, location );
strip_events( &obj->events, evn_imp_grab );
}
return;
}
/*
* Trigger a sub_prog on another mobile.
* Usage: trigger <mob> <trigger>
* The mobile need not be visible to the triggerer if
* it is in the same room.
*/
void mp_trigger( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *mob;
char arg[MAX_INPUT_LENGTH];
char name[MAX_INPUT_LENGTH];
int count;
argument = one_argument( argument, arg );
count = number_argument( arg, name );
for( mob = ch->in_room->people; mob; mob = mob->next_in_room )
{
if( !mob->deleted && is_char_name( mob, name ) && --count <= 0 )
break;
}
if( !mob )
mob = get_char_world( ch, arg );
if( arg[0] == '\0' || argument[0] == '\0' || !mob || mob == ch
|| !IS_NPC( mob ) )
{
progbug( ch, "Bad arguments to mptrigger mob." );
return;
}
mprog_sub_trigger( mob, ch, argument );
return;
}
/* Trimmed down and silent version of do_open with no triggers or traps */
void mp_open( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
int door;
if( argument[0] == '\0' )
{
progbug( ch, "Trying to open nothingness." );
return;
}
if( ( door = find_door( ch, argument ) ) >= 0 )
{
/* 'open door' */
EXIT_DATA *pexit;
EXIT_DATA *pexit_rev;
ROOM_INDEX_DATA *to_room;
pexit = ch->in_room->exit[door];
REMOVE_BIT( pexit->exit_info, EX_CLOSED );
/*
* open the other side
*/
if( ( to_room = pexit->to_room )
&& ( pexit_rev = to_room->exit[rev_dir[door]] )
&& pexit_rev->to_room == ch->in_room )
REMOVE_BIT( pexit_rev->exit_info, EX_CLOSED );
return;
}
if( ( obj = get_obj_here( ch, argument ) ) )
{
/* 'open object' */
if( obj->item_type != ITEM_CONTAINER )
{
progbug( ch, "Trying to open a non-container '%s'.",
argument );
return;
}
if( !IS_SET( obj->value[1], CONT_CLOSEABLE ) )
{
progbug( ch, "Trying to open a non-closable '%s'.",
argument );
return;
}
REMOVE_BIT( obj->value[1], CONT_CLOSED );
return;
}
progbug( ch, "Couldn't open a '%s'.", argument );
return;
}
/* Trimmed down and silent version of do_close with no triggers or traps */
void mp_close( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
int door;
if( argument[0] == '\0' )
{
progbug( ch, "Trying to close nothingness." );
return;
}
if( ( door = find_door( ch, argument ) ) >= 0 )
{
/*
'close door'
*/
EXIT_DATA *pexit;
EXIT_DATA *pexit_rev;
ROOM_INDEX_DATA *to_room;
pexit = ch->in_room->exit[door];
SET_BIT( pexit->exit_info, EX_CLOSED );
/*
close the other side
*/
if( ( to_room = pexit->to_room )
&& ( pexit_rev = to_room->exit[rev_dir[door]] )
&& pexit_rev->to_room == ch->in_room )
SET_BIT( pexit_rev->exit_info, EX_CLOSED );
return;
}
if( ( obj = get_obj_here( ch, argument ) ) )
{
if( obj->item_type != ITEM_CONTAINER )
{
progbug( ch, "Trying to open a non-container '%s'.",
argument );
return;
}
if( !IS_SET( obj->value[1], CONT_CLOSEABLE ) )
{
progbug( ch, "Trying to open a non-closable '%s'.",
argument );
return;
}
SET_BIT( obj->value[1], CONT_CLOSED );
return;
}
progbug( ch, "Couldn't close a '%s'.", argument );
return;
}
/* Trimmed down and silent version of do_lock. */
void mp_lock( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
int door;
if( argument[0] == '\0' )
{
progbug( ch, "Trying to lock nothingness." );
return;
}
if( ( door = find_door( ch, argument ) ) >= 0 )
{
/*
'lock door'
*/
EXIT_DATA *pexit;
EXIT_DATA *pexit_rev;
ROOM_INDEX_DATA *to_room;
pexit = ch->in_room->exit[door];
if( !IS_SET( pexit->exit_info, EX_CLOSED ) )
{
progbug( ch, "Trying to lock an open door." );
return;
}
/* Let's just see if this causes problems, it should be ok as the
resets still take care of these.
if( pexit->key < 0 )
{
progbug( ch, "Trying to lock an unlockable door." );
return;
}
*/
if( IS_SET( pexit->exit_info, EX_LOCKED ) )
return;
SET_BIT( pexit->exit_info, EX_LOCKED );
/*
lock the other side
*/
if( ( to_room = pexit->to_room )
&& ( pexit_rev = to_room->exit[rev_dir[door]] )
&& pexit_rev->to_room == ch->in_room )
SET_BIT( pexit_rev->exit_info, EX_LOCKED );
return;
}
if( ( obj = get_obj_here( ch, argument ) ) )
{
/*
'lock object'
*/
if( obj->item_type != ITEM_CONTAINER )
{
progbug( ch, "Trying to lock a non-container '%s'.",
argument );
return;
}
if( !IS_SET( obj->value[1], CONT_CLOSED ) )
{
progbug( ch, "Trying to lock an open container '%s'.",
argument );
return;
}
if( obj->value[2] < 0 )
{
progbug( ch, "Trying to lock an unlockable container '%s'.",
argument );
return;
}
if( IS_SET( obj->value[1], CONT_LOCKED ) )
return;
SET_BIT( obj->value[1], CONT_LOCKED );
return;
}
progbug( ch, "Trying to lock non-existant '%s'", argument );
return;
}
/* Trimmed down, safe and silent version of do_unlock */
void mp_unlock( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
int door;
if( argument[0] == '\0' )
{
progbug( ch, "Trying to unlock nothingness." );
return;
}
if( ( door = find_door( ch, argument ) ) >= 0 )
{
/* 'unlock door' */
EXIT_DATA *pexit;
EXIT_DATA *pexit_rev;
ROOM_INDEX_DATA *to_room;
pexit = ch->in_room->exit[door];
if( !IS_SET( pexit->exit_info, EX_CLOSED ) )
return;
if( !IS_SET( pexit->exit_info, EX_LOCKED ) )
return;
REMOVE_BIT( pexit->exit_info, EX_LOCKED );
/* unlock the other side */
if( ( to_room = pexit->to_room )
&& ( pexit_rev = to_room->exit[rev_dir[door]] )
&& pexit_rev->to_room == ch->in_room )
REMOVE_BIT( pexit_rev->exit_info, EX_LOCKED );
return;
}
if( ( obj = get_obj_here( ch, argument ) ) )
{
/* 'unlock object' */
if( obj->item_type != ITEM_CONTAINER )
{
progbug( ch, "Trying to unlock a non-container '%s'.",
argument );
return;
}
if( !IS_SET( obj->value[1], CONT_CLOSED ) )
return;
if( !IS_SET( obj->value[1], CONT_LOCKED ) )
return;
REMOVE_BIT( obj->value[1], CONT_LOCKED );
return;
}
progbug( ch, "Trying to unlock non-existant '%s'.", argument );
return;
}