/****************************************************************************
* _______ _ ______ _______ _______ ______ *
* ( ____ \( \ ( __ \ |\ /|( ___ )( )|\ /|( __ \ *
* | ( \/| ( | ( \ )| ) ( || ( ) || () () || ) ( || ( \ ) *
* | (__ | | | | ) || (___) || (___) || || || || | | || | ) | *
* | __) | | | | | || ___ || ___ || |(_)| || | | || | | | *
* | ( | | | | ) || ( ) || ( ) || | | || | | || | ) | *
* | (____/\| (____/\| (__/ )| ) ( || ) ( || ) ( || (___) || (__/ ) *
* (_______/(_______/(______/ |/ \||/ \||/ \|(_______)(______/ *
* +-+-+-+ +-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+ *
* |T|h|e| |O|a|k|l|a|n|d| |C|h|r|o|n|i|c|l|e|s| *
* +-+-+-+ +-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+ *
* ------------------------------------------------------------------------- *
* EldhaMUD code (C) 2003-2005 by Robert Powell (Tommi) *
* EldhaMUD Team: Celest, Altere and Krelowyn *
* ------------------------------------------------------------------------- *
* *
****************************************************************************/
/****************************************************************************
* [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// *
* -----------------------------------------------------------| (0...0) *
* SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by Derek Snider | ).:.( *
* -----------------------------------------------------------| {o o} *
* SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ *
* Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek, |~'~.VxvxV.~'~*
* Tricops and Fireblade | *
****************************************************************************
* The MUDprograms are heavily based on the original MOBprogram code that *
* was written by N'Atas-ha. *
* Much has been added, including the capability to put a "program" on *
* rooms and objects, not to mention many more triggers and ifchecks, as *
* well as "script" support. *
* *
* Error reporting has been changed to specify whether the offending *
* program is on a mob, a room or and object, along with the vnum. *
* *
* Mudprog parsing has been rewritten (in mprog_driver). Mprog_process_if *
* and mprog_process_cmnd have been removed, mprog_do_command is new. *
* Full support for nested ifs is in. *
****************************************************************************/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "./Headers/mud.h"
/*
* Recursive function used by the carryingvnum ifcheck.
* It loops thru all objects belonging to a char (in nested containers)
* and returns TRUE if it finds a matching vnum.
* I declared it static to limit its scope to this file. --Gorog
*
* This recursive function works by using the following method for
* traversing the nodes in a binary tree:
*
* Start at the root node
* if there is a child then visit the child
* if there is a sibling then visit the sibling
* else
* if there is a sibling then visit the sibling
*/
static bool carryingvnum_visit( CHAR_DATA * ch, OBJ_DATA * obj, int vnum )
{
/*
* pager_printf(ch, "***obj=%s vnum=%d\n\r", obj->name, obj->pIndexData->vnum );
*/
if( obj->wear_loc == -1 && obj->pIndexData->vnum == vnum )
return TRUE;
if( obj->first_content ) /* node has a child? */
{
if( carryingvnum_visit( ch, obj->first_content, vnum ) )
return TRUE;
if( obj->next_content ) /* node has a sibling? */
if( carryingvnum_visit( ch, obj->next_content, vnum ) )
return TRUE;
}
else if( obj->next_content ) /* node has a sibling? */
if( carryingvnum_visit( ch, obj->next_content, vnum ) )
return TRUE;
return FALSE;
}
/* Defines by Narn for new mudprog parsing, used as
return values from mprog_do_command. */
#define COMMANDOK 1
#define IFTRUE 2
#define IFFALSE 3
#define ORTRUE 4
#define ORFALSE 5
#define FOUNDELSE 6
#define FOUNDENDIF 7
#define IFIGNORED 8
#define ORIGNORED 9
int mprog_do_command( char *cmnd, CHAR_DATA * mob, CHAR_DATA * actor,
OBJ_DATA * obj, void *vo, CHAR_DATA * rndm, bool ignore, bool ignore_ors );
/*
* Mudprogram additions
*/
CHAR_DATA *supermob;
struct act_prog_data *room_act_list;
struct act_prog_data *obj_act_list;
struct act_prog_data *mob_act_list;
/*
* Global variables to handle sleeping mud progs.
*/
MPSLEEP_DATA *first_mpsleep = NULL;
MPSLEEP_DATA *last_mpsleep = NULL;
MPSLEEP_DATA *current_mpsleep = NULL;
/*
* Local function prototypes
*/
char *mprog_next_command args( ( char *clist ) );
bool mprog_seval args( ( char *lhs, char *opr, char *rhs, CHAR_DATA * mob ) );
bool mprog_veval args( ( int lhs, char *opr, int rhs, CHAR_DATA * mob ) );
int mprog_do_ifcheck args( ( char *ifcheck, CHAR_DATA * mob,
CHAR_DATA * actor, OBJ_DATA * obj, void *vo, CHAR_DATA * rndm ) );
void mprog_translate args( ( char ch, char *t, CHAR_DATA * mob,
CHAR_DATA * actor, OBJ_DATA * obj, void *vo, CHAR_DATA * rndm ) );
void mprog_driver args( ( char *com_list, CHAR_DATA * mob, CHAR_DATA * actor, OBJ_DATA * obj, void *vo, bool single_step ) );
bool mprog_keyword_check args( ( const char *argu, const char *argl ) );
void oprog_wordlist_check( char *arg, CHAR_DATA * mob, CHAR_DATA * actor, OBJ_DATA * obj, void *vo, int type,
OBJ_DATA * iobj );
void set_supermob( OBJ_DATA * obj );
bool oprog_percent_check( CHAR_DATA * mob, CHAR_DATA * actor, OBJ_DATA * obj, void *vo, int type );
void rprog_percent_check( CHAR_DATA * mob, CHAR_DATA * actor, OBJ_DATA * obj, void *vo, int type );
void rprog_wordlist_check( char *arg, CHAR_DATA * mob, CHAR_DATA * actor,
OBJ_DATA * obj, void *vo, int type, ROOM_INDEX_DATA * room );
char *strip_tilde( char *str )
{
static char newstr[MAX_STRING_LENGTH];
int i, j;
for( i = j = 0; str[i] != '\0'; i++ )
if( str[i] != '~' )
{
newstr[j++] = str[i];
}
newstr[j] = '\0';
return newstr;
}
/*
new quest shizat
*/
#define DT_QUEST_DIR "../quests/"
void MarkQuestComplete( char *quest, CHAR_DATA * player );
bool CheckQuestComplete( char *quest, CHAR_DATA * player );
/*
MarkQuestComplete
Appends the line passed to it to the player's quest file.
Note that it could duplicate quests if marked more than once,
so use if questcomplete before calling this.
*/
void MarkQuestComplete( char *quest, CHAR_DATA * player )
{
char quest_file[100];
FILE *fw;
strcpy( quest_file, DT_QUEST_DIR );
strcat( quest_file, player->name );
strcat( quest_file, ".qdt" );
fw = NULL;
fw = fopen( quest_file, "a" );
fprintf( fw, "%s\n", quest );
printf( "stuck %s in %s - correct?\n", quest, quest_file );
fclose( fw );
}
/*
CheckQuestComplete
finds the quest entry in /quests/player_name.qdt, and returns 1 if
found.
*/
bool CheckQuestComplete( char *quest, CHAR_DATA * player )
{
char quest_file[100];
char read_string[100];
bool bFound;
FILE *read_l;
strcpy( quest_file, DT_QUEST_DIR );
strcat( quest_file, player->name );
strcat( quest_file, ".qdt" );
read_l = fopen( quest_file, "r" );
bFound = 0;
if( read == NULL )
{
return FALSE;
}
while( fgets( read_string, 99, read_l ) != NULL )
{
if( read_string[strlen( read_string ) - 1] == '\n' )
{
read_string[strlen( read_string ) - 1] = '\0';
}
if( !str_cmp( quest, read_string ) )
{
bFound = 1;
break;
}
}
return bFound;
}
/***************************************************************************
* Local function code and brief comments.
*/
/* if you dont have these functions, you damn well should... */
#ifdef DUNNO_STRSTR
char *strstr( s1, s2 )
const char *s1;
const char *s2;
{
char *cp;
int i, j = strlen( s1 ) - strlen( s2 ), k = strlen( s2 );
if( j < 0 )
return NULL;
for( i = 0; i <= j && strncmp( s1++, s2, k ) != 0; i++ )
;
return ( i > j ) ? NULL : ( s1 - 1 );
}
#endif
#define RID ROOM_INDEX_DATA
void init_supermob( void )
{
RID *office;
supermob = create_mobile( get_mob_index( 3 ) );
office = get_room_index( 3 );
char_to_room( supermob, office );
#ifdef NOTDEFD
CREATE( supermob, CHAR_DATA, 1 );
clear_char( supermob );
xSET_BIT( supermob->act, ACT_IS_NPC );
supermob->name = STRALLOC( "supermob" );
supermob->short_descr = STRALLOC( "supermob" );
supermob->long_descr = STRALLOC( "supermob is here" );
CREATE( supermob_index, MOB_INDEX_DATA, 1 )
#endif
}
#undef RID
/* Used to get sequential lines of a multi line string (separated by "\n\r")
* Thus its like one_argument(), but a trifle different. It is destructive
* to the multi line string argument, and thus clist must not be shared.
*/
char *mprog_next_command( char *clist )
{
bool Append = FALSE;
char *pointer = clist;
while( *pointer != '\0' )
{
if( Append == FALSE && ( *pointer == '\n' || *pointer == '\r' ) )
break;
if( Append == TRUE && *pointer != '\n' && *pointer != '\r' )
Append = FALSE;
else if( Append == TRUE && ( *pointer == '\n' || *pointer == '\r' ) )
{
/*
* A tilde is one symbol we can be absolutely certain never
* to have as part of a prog, so can replace the returns with
* tildes, and then later we will strip all tildes from the
* output before its parse the final time.
*/
*pointer = '~';
}
if( *pointer == '+' )
{
Append = TRUE;
*pointer = ' ';
}
pointer++;
}
if( *pointer == '\n' )
*pointer++ = '\0';
if( *pointer == '\r' )
*pointer++ = '\0';
return ( pointer );
}
/* These two functions do the basic evaluation of ifcheck operators.
* It is important to note that the string operations are not what
* you probably expect. Equality is exact and division is substring.
* remember that lhs has been stripped of leading space, but can
* still have trailing spaces so be careful when editing since:
* "guard" and "guard " are not equal.
*/
bool mprog_seval( char *lhs, char *opr, char *rhs, CHAR_DATA * mob )
{
if( !str_cmp( opr, "==" ) )
return ( bool ) ( !str_cmp( lhs, rhs ) );
if( !str_cmp( opr, "!=" ) )
return ( bool ) ( str_cmp( lhs, rhs ) );
if( !str_cmp( opr, "/" ) )
return ( bool ) ( !str_infix( rhs, lhs ) );
if( !str_cmp( opr, "!/" ) )
return ( bool ) ( str_infix( rhs, lhs ) );
sprintf( log_buf, "Improper MOBprog operator '%s'", opr );
progbug( log_buf, mob );
return 0;
}
bool mprog_veval( int lhs, char *opr, int rhs, CHAR_DATA * mob )
{
if( !str_cmp( opr, "==" ) )
return ( lhs == rhs );
if( !str_cmp( opr, "!=" ) )
return ( lhs != rhs );
if( !str_cmp( opr, ">" ) )
return ( lhs > rhs );
if( !str_cmp( opr, "<" ) )
return ( lhs < rhs );
if( !str_cmp( opr, "<=" ) )
return ( lhs <= rhs );
if( !str_cmp( opr, ">=" ) )
return ( lhs >= rhs );
if( !str_cmp( opr, "&" ) )
return ( lhs & rhs );
if( !str_cmp( opr, "|" ) )
return ( lhs | rhs );
sprintf( log_buf, "Improper MOBprog operator '%s'", opr );
progbug( log_buf, mob );
return 0;
}
#define isoperator(c) ((c)=='='||(c)=='<'||(c)=='>'||(c)=='!'||(c)=='&'||(c)=='|')
#define MAX_IF_ARGS 6
/*
* This function performs the evaluation of the if checks. It is
* here that you can add any ifchecks which you so desire. Hopefully
* it is clear from what follows how one would go about adding your
* own. The syntax for an if check is: ifcheck ( arg ) [opr val]
* where the parenthesis are required and the opr and val fields are
* optional but if one is there then both must be. The spaces are all
* optional. The evaluation of the opr expressions is farmed out
* to reduce the redundancy of the mammoth if statement list.
* If there are errors, then return BERR otherwise return boolean 1,0
* Redone by Altrag.. kill all that big copy-code that performs the
* same action on each variable..
*/
int mprog_do_ifcheck( char *ifcheck, CHAR_DATA * mob, CHAR_DATA * actor, OBJ_DATA * obj, void *vo, CHAR_DATA * rndm )
{
char buf[MAX_STRING_LENGTH];
char opr[MAX_INPUT_LENGTH];
char *chck, *cvar;
char *argv[MAX_IF_ARGS];
char *rval = "";
char *q, *p = buf;
int argc = 0;
CHAR_DATA *chkchar = NULL;
OBJ_DATA *chkobj = NULL;
int lhsvl, rhsvl = 0;
if( !*ifcheck )
{
progbug( "Null ifcheck", mob );
return BERR;
}
/*
* New parsing by Thoric to allow for multiple arguments inside the
* brackets, ie: if leveldiff($n, $i) > 10
* It's also smaller, cleaner and probably faster
*/
strcpy( buf, ifcheck );
opr[0] = '\0';
while( isspace( *p ) )
++p;
argv[argc++] = p;
while( isalnum( *p ) )
++p;
while( isspace( *p ) )
*p++ = '\0';
if( *p != '(' )
{
progbug( "Ifcheck Syntax error (missing left bracket)", mob );
return BERR;
}
*p++ = '\0';
/*
* Need to check for spaces or if name( $n ) isn't legal --Shaddai
*/
while( isspace( *p ) )
*p++ = '\0';
for( ;; )
{
argv[argc++] = p;
while( *p == '$' || isalnum( *p ) )
++p;
while( isspace( *p ) )
*p++ = '\0';
switch ( *p )
{
case ',':
*p++ = '\0';
while( isspace( *p ) )
*p++ = '\0';
if( argc >= MAX_IF_ARGS )
{
while( *p && *p != ')' )
++p;
if( *p )
*p++ = '\0';
while( isspace( *p ) )
*p++ = '\0';
goto doneargs;
}
break;
case ')':
*p++ = '\0';
while( isspace( *p ) )
*p++ = '\0';
goto doneargs;
break;
default:
progbug( "Ifcheck Syntax warning (missing right bracket)", mob );
goto doneargs;
break;
}
}
doneargs:
q = p;
while( isoperator( *p ) )
++p;
strncpy( opr, q, p - q );
opr[p - q] = '\0';
while( isspace( *p ) )
*p++ = '\0';
rval = p;
/*
* while ( *p && !isspace(*p) ) ++p;
*/
while( *p )
++p;
*p = '\0';
chck = argv[0] ? argv[0] : "";
cvar = argv[1] ? argv[1] : "";
/*
* chck contains check, cvar is the variable in the (), opr is the
* operator if there is one, and rval is the value if there was an
* operator.
*/
if( cvar[0] == '$' )
{
switch ( cvar[1] )
{
case 'i':
chkchar = mob;
break;
case 'n':
chkchar = actor;
break;
case 't':
chkchar = ( CHAR_DATA * ) vo;
break;
case 'r':
chkchar = rndm;
break;
case 'o':
chkobj = obj;
break;
case 'p':
chkobj = ( OBJ_DATA * ) vo;
break;
default:
sprintf( rval, "Bad argument '%c' to '%s'", cvar[0], chck );
progbug( rval, mob );
return BERR;
}
if( !chkchar && !chkobj )
return BERR;
}
if( !str_cmp( chck, "rand" ) )
{
return ( number_percent( ) <= atoi( cvar ) );
}
if( !str_cmp( chck, "economy" ) )
{
int idx = atoi( cvar );
ROOM_INDEX_DATA *room;
if( !idx )
{
if( !mob->in_room )
{
progbug( "'economy' ifcheck: mob in NULL room with no room vnum " "argument", mob );
return BERR;
}
room = mob->in_room;
}
else
room = get_room_index( idx );
if( !room )
{
progbug( "Bad room vnum passed to 'economy'", mob );
return BERR;
}
return mprog_veval( ( ( room->area->high_economy > 0 ) ? 1000000000 : 0 )
+ room->area->low_economy, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "mobinarea" ) )
{
int vnum = atoi( cvar );
int world_count;
int found_count;
CHAR_DATA *tmob;
MOB_INDEX_DATA *m_index;
if( vnum < 1 || vnum > MAX_VNUM )
{
progbug( "Bad vnum to 'mobinarea'", mob );
return BERR;
}
m_index = get_mob_index( vnum );
if( !m_index )
world_count = 0;
else
world_count = m_index->count;
lhsvl = 0;
found_count = 0;
for( tmob = first_char; tmob && found_count != world_count; tmob = tmob->next )
{
if( IS_NPC( tmob ) && tmob->pIndexData->vnum == vnum )
{
found_count++;
if( tmob->in_room->area == mob->in_room->area )
lhsvl++;
}
}
rhsvl = atoi( rval );
/*
* Changed below from 1 to 0
*/
if( rhsvl < 0 )
rhsvl = 0;
if( !*opr )
strcpy( opr, "==" );
return mprog_veval( lhsvl, opr, rhsvl, mob );
}
if( !str_cmp( chck, "mobinroom" ) )
{
int vnum = atoi( cvar );
CHAR_DATA *oMob;
if( vnum < 1 || vnum > MAX_VNUM )
{
progbug( "Bad vnum to 'mobinroom'", mob );
return BERR;
}
lhsvl = 0;
for( oMob = mob->in_room->first_person; oMob; oMob = oMob->next_in_room )
if( IS_NPC( oMob ) && oMob->pIndexData->vnum == vnum )
lhsvl++;
rhsvl = atoi( rval );
/*
* Changed below from 1 to 0
*/
if( rhsvl < 0 )
rhsvl = 0;
if( !*opr )
strcpy( opr, "==" );
return mprog_veval( lhsvl, opr, rhsvl, mob );
}
if( !str_cmp( chck, "mobinworld" ) )
{
int vnum = atoi( cvar );
MOB_INDEX_DATA *m_index;
if( vnum < 1 || vnum > MAX_VNUM )
{
progbug( "Bad vnum to 'mobinworld'", mob );
return BERR;
}
m_index = get_mob_index( vnum );
if( !m_index )
lhsvl = 0;
else
lhsvl = m_index->count;
rhsvl = atoi( rval );
/*
* Changed below from 1 to 0
*/
if( rhsvl < 0 )
rhsvl = 0;
if( !*opr )
strcpy( opr, "==" );
return mprog_veval( lhsvl, opr, rhsvl, mob );
}
if( !str_cmp( chck, "timeskilled" ) )
{
MOB_INDEX_DATA *pMob;
if( chkchar )
pMob = chkchar->pIndexData;
else if( !( pMob = get_mob_index( atoi( cvar ) ) ) )
{
progbug( "TimesKilled ifcheck: bad vnum", mob );
return BERR;
}
return mprog_veval( pMob->killed, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "ovnumhere" ) )
{
OBJ_DATA *pObj;
int vnum = atoi( cvar );
if( vnum < 1 || vnum > MAX_VNUM )
{
progbug( "OvnumHere: bad vnum", mob );
return BERR;
}
lhsvl = 0;
for( pObj = mob->first_carrying; pObj; pObj = pObj->next_content )
if( pObj->pIndexData->vnum == vnum )
lhsvl += pObj->count;
for( pObj = mob->in_room->first_content; pObj; pObj = pObj->next_content )
if( pObj->pIndexData->vnum == vnum )
lhsvl += pObj->count;
rhsvl = is_number( rval ) ? atoi( rval ) : -1;
/*
* Changed from 1 to 0
*/
if( rhsvl < 0 )
rhsvl = 0;
if( !*opr )
strcpy( opr, "==" );
return mprog_veval( lhsvl, opr, rhsvl, mob );
}
if( !str_cmp( chck, "otypehere" ) )
{
OBJ_DATA *pObj;
int type;
if( is_number( cvar ) )
type = atoi( cvar );
else
type = get_otype( cvar );
if( type < 0 || type > MAX_ITEM_TYPE )
{
progbug( "OtypeHere: bad type", mob );
return BERR;
}
lhsvl = 0;
for( pObj = mob->first_carrying; pObj; pObj = pObj->next_content )
if( pObj->item_type == type )
lhsvl += pObj->count;
for( pObj = mob->in_room->first_content; pObj; pObj = pObj->next_content )
if( pObj->item_type == type )
lhsvl += pObj->count;
rhsvl = is_number( rval ) ? atoi( rval ) : -1;
/*
* Change below from 1 to 0
*/
if( rhsvl < 0 )
rhsvl = 0;
if( !*opr )
strcpy( opr, "==" );
return mprog_veval( lhsvl, opr, rhsvl, mob );
}
if( !str_cmp( chck, "ovnumroom" ) )
{
OBJ_DATA *pObj;
int vnum = atoi( cvar );
if( vnum < 1 || vnum > MAX_VNUM )
{
progbug( "OvnumRoom: bad vnum", mob );
return BERR;
}
lhsvl = 0;
for( pObj = mob->in_room->first_content; pObj; pObj = pObj->next_content )
if( pObj->pIndexData->vnum == vnum )
lhsvl += pObj->count;
rhsvl = is_number( rval ) ? atoi( rval ) : -1;
/*
* Changed below from 1 to 0 so can check for == no items Shaddai
*/
if( rhsvl < 0 )
rhsvl = 0;
if( !*opr )
strcpy( opr, "==" );
return mprog_veval( lhsvl, opr, rhsvl, mob );
}
if( !str_cmp( chck, "otyperoom" ) )
{
OBJ_DATA *pObj;
int type;
if( is_number( cvar ) )
type = atoi( cvar );
else
type = get_otype( cvar );
if( type < 0 || type > MAX_ITEM_TYPE )
{
progbug( "OtypeRoom: bad type", mob );
return BERR;
}
lhsvl = 0;
for( pObj = mob->in_room->first_content; pObj; pObj = pObj->next_content )
if( pObj->item_type == type )
lhsvl += pObj->count;
rhsvl = is_number( rval ) ? atoi( rval ) : -1;
/*
* Changed below from 1 to 0
*/
if( rhsvl < 0 )
rhsvl = 0;
if( !*opr )
strcpy( opr, "==" );
return mprog_veval( lhsvl, opr, rhsvl, mob );
}
if( !str_cmp( chck, "ovnumcarry" ) )
{
OBJ_DATA *pObj;
int vnum = atoi( cvar );
if( vnum < 1 || vnum > MAX_VNUM )
{
progbug( "OvnumCarry: bad vnum", mob );
return BERR;
}
lhsvl = 0;
for( pObj = mob->first_carrying; pObj; pObj = pObj->next_content )
if( pObj->pIndexData->vnum == vnum )
lhsvl += pObj->count;
rhsvl = is_number( rval ) ? atoi( rval ) : -1;
if( rhsvl < 0 )
rhsvl = 0;
if( !*opr )
strcpy( opr, "==" );
return mprog_veval( lhsvl, opr, rhsvl, mob );
}
if( !str_cmp( chck, "otypecarry" ) )
{
OBJ_DATA *pObj;
int type;
if( is_number( cvar ) )
type = atoi( cvar );
else
type = get_otype( cvar );
if( type < 0 || type > MAX_ITEM_TYPE )
{
progbug( "OtypeCarry: bad type", mob );
return BERR;
}
lhsvl = 0;
for( pObj = mob->first_carrying; pObj; pObj = pObj->next_content )
if( pObj->item_type == type )
lhsvl += pObj->count;
rhsvl = is_number( rval ) ? atoi( rval ) : -1;
/*
* Changed below from 1 to 0 Shaddai
*/
if( rhsvl < 0 )
rhsvl = 0;
if( !*opr )
strcpy( opr, "==" );
return mprog_veval( lhsvl, opr, rhsvl, mob );
}
if( !str_cmp( chck, "ovnumwear" ) )
{
OBJ_DATA *pObj;
int vnum = atoi( cvar );
if( vnum < 1 || vnum > MAX_VNUM )
{
progbug( "OvnumWear: bad vnum", mob );
return BERR;
}
lhsvl = 0;
for( pObj = mob->first_carrying; pObj; pObj = pObj->next_content )
if( pObj->wear_loc != WEAR_NONE && pObj->pIndexData->vnum == vnum )
lhsvl += pObj->count;
rhsvl = is_number( rval ) ? atoi( rval ) : -1;
/*
* Changed below from 1 to 0
*/
if( rhsvl < 0 )
rhsvl = 0;
if( !*opr )
strcpy( opr, "==" );
return mprog_veval( lhsvl, opr, rhsvl, mob );
}
if( !str_cmp( chck, "otypewear" ) )
{
OBJ_DATA *pObj;
int type;
if( is_number( cvar ) )
type = atoi( cvar );
else
type = get_otype( cvar );
if( type < 0 || type > MAX_ITEM_TYPE )
{
progbug( "OtypeWear: bad type", mob );
return BERR;
}
lhsvl = 0;
for( pObj = mob->first_carrying; pObj; pObj = pObj->next_content )
if( pObj->wear_loc != WEAR_NONE && pObj->item_type == type )
lhsvl += pObj->count;
rhsvl = is_number( rval ) ? atoi( rval ) : -1;
/*
* Changed below from 1 to 0 so can have == 0 Shaddai
*/
if( rhsvl < 0 )
rhsvl = 0;
if( !*opr )
strcpy( opr, "==" );
return mprog_veval( lhsvl, opr, rhsvl, mob );
}
if( !str_cmp( chck, "ovnuminv" ) )
{
OBJ_DATA *pObj;
int vnum = atoi( cvar );
if( vnum < 1 || vnum > MAX_VNUM )
{
progbug( "OvnumInv: bad vnum", mob );
return BERR;
}
lhsvl = 0;
for( pObj = mob->first_carrying; pObj; pObj = pObj->next_content )
if( pObj->wear_loc == WEAR_NONE && pObj->pIndexData->vnum == vnum )
lhsvl += pObj->count;
rhsvl = is_number( rval ) ? atoi( rval ) : -1;
/*
* Changed 1 to 0 so can have == 0
*/
if( rhsvl < 0 )
rhsvl = 0;
if( !*opr )
strcpy( opr, "==" );
return mprog_veval( lhsvl, opr, rhsvl, mob );
}
if( !str_cmp( chck, "otypeinv" ) )
{
OBJ_DATA *pObj;
int type;
if( is_number( cvar ) )
type = atoi( cvar );
else
type = get_otype( cvar );
if( type < 0 || type > MAX_ITEM_TYPE )
{
progbug( "OtypeInv: bad type", mob );
return BERR;
}
lhsvl = 0;
for( pObj = mob->first_carrying; pObj; pObj = pObj->next_content )
if( pObj->wear_loc == WEAR_NONE && pObj->item_type == type )
lhsvl += pObj->count;
rhsvl = is_number( rval ) ? atoi( rval ) : -1;
/*
* Changed below from 1 to 0 for == 0 Shaddai
*/
if( rhsvl < 0 )
rhsvl = 0;
if( !*opr )
strcpy( opr, "==" );
return mprog_veval( lhsvl, opr, rhsvl, mob );
}
if( chkchar )
{
if( !str_cmp( chck, "ispacifist" ) )
{
return ( IS_NPC( chkchar ) && xIS_SET( chkchar->act, ACT_PACIFIST ) );
}
if( !str_cmp( chck, "ismobinvis" ) )
{
return ( IS_NPC( chkchar ) && xIS_SET( chkchar->act, ACT_MOBINVIS ) );
}
if( !str_cmp( chck, "mobinvislevel" ) )
{
return ( IS_NPC( chkchar ) ? mprog_veval( chkchar->mobinvis, opr, atoi( rval ), mob ) : FALSE );
}
if( !str_cmp( chck, "ispc" ) )
{
return IS_NPC( chkchar ) ? FALSE : TRUE;
}
if( !str_cmp( chck, "isnpc" ) )
{
return IS_NPC( chkchar ) ? TRUE : FALSE;
}
if( !str_cmp( chck, "cansee" ) )
{
return can_see( mob, chkchar, FALSE );
}
if( !str_cmp( chck, "ispassage" ) )
{
if( find_door( chkchar, rval, TRUE ) == NULL )
return FALSE;
else
return TRUE;
}
if( !str_cmp( chck, "isopen" ) )
{
EXIT_DATA *pexit;
if( ( pexit = find_door( chkchar, rval, TRUE ) ) == NULL )
return FALSE;
if( !IS_SET( pexit->exit_info, EX_CLOSED ) )
return TRUE;
return FALSE;
}
if( !str_cmp( chck, "islocked" ) )
{
EXIT_DATA *pexit;
if( ( pexit = find_door( chkchar, rval, TRUE ) ) == NULL )
return FALSE;
if( IS_SET( pexit->exit_info, EX_LOCKED ) )
return TRUE;
return FALSE;
}
if( !str_cmp( chck, "ispkill" ) )
{
return IS_PKILL( chkchar ) ? TRUE : FALSE;
}
if( !str_cmp( chck, "isdevoted" ) )
{
return IS_DEVOTED( chkchar ) ? TRUE : FALSE;
}
if( !str_cmp( chck, "canpkill" ) )
{
return CAN_PKILL( chkchar ) ? TRUE : FALSE;
}
if( !str_cmp( chck, "ismounted" ) )
{
return ( chkchar->position == POS_MOUNTED );
}
if( !str_cmp( chck, "ismorphed" ) )
{
return ( chkchar->morph != NULL ) ? TRUE : FALSE;
}
if( !str_cmp( chck, "isnuisance" ) )
{
return ( !IS_NPC( chkchar ) ? chkchar->pcdata->nuisance ? TRUE : FALSE : FALSE );
}
if( !str_cmp( chck, "isgood" ) )
{
return IS_GOOD( chkchar ) ? TRUE : FALSE;
}
if( !str_cmp( chck, "isneutral" ) )
{
return IS_NEUTRAL( chkchar ) ? TRUE : FALSE;
}
if( !str_cmp( chck, "isevil" ) )
{
return IS_EVIL( chkchar ) ? TRUE : FALSE;
}
if( !str_cmp( chck, "isfight" ) )
{
return who_fighting( chkchar ) ? TRUE : FALSE;
}
if( !str_cmp( chck, "isimmort" ) )
{
return ( get_trust( chkchar ) >= LEVEL_IMMORTAL );
}
if( !str_cmp( chck, "ischarmed" ) )
{
return IS_AFFECTED( chkchar, AFF_CHARM ) ? TRUE : FALSE;
}
if( !str_cmp( chck, "isflying" ) )
{
return IS_AFFECTED( chkchar, AFF_FLYING ) ? TRUE : FALSE;
}
if( !str_cmp( chck, "isthief" ) )
{
return ( !IS_NPC( chkchar ) && xIS_SET( chkchar->act, PLR_THIEF ) );
}
if( !str_cmp( chck, "isattacker" ) )
{
return ( !IS_NPC( chkchar ) && xIS_SET( chkchar->act, PLR_ATTACKER ) );
}
if( !str_cmp( chck, "iskiller" ) )
{
return ( !IS_NPC( chkchar ) && xIS_SET( chkchar->act, PLR_KILLER ) );
}
if( !str_cmp( chck, "isfollow" ) )
{
return ( chkchar->master != NULL && chkchar->master->in_room == chkchar->in_room );
}
if( !str_cmp( chck, "isaffected" ) )
{
int value = get_aflag( rval );
if( value < 0 || value > MAX_BITS )
{
progbug( "Unknown affect being checked", mob );
return BERR;
}
return IS_AFFECTED( chkchar, value ) ? TRUE : FALSE;
}
if( !str_cmp( chck, "numfighting" ) )
{
return mprog_veval( chkchar->num_fighting - 1, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "hitprcnt" ) )
{
return mprog_veval( ( chkchar->hit * 100 ) / chkchar->max_hit, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "inroom" ) )
{
return mprog_veval( chkchar->in_room->vnum, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "wasinroom" ) )
{
if( !chkchar->was_in_room )
return FALSE;
return mprog_veval( chkchar->was_in_room->vnum, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "norecall" ) )
{
return xIS_SET( chkchar->in_room->room_flags, ROOM_NO_RECALL ) ? TRUE : FALSE;
}
if( !str_cmp( chck, "sex" ) )
{
return mprog_veval( chkchar->sex, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "position" ) )
{
return mprog_veval( chkchar->position, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "doingquest" ) )
{
return IS_NPC( chkchar ) ? FALSE : mprog_veval( chkchar->pcdata->quest_number, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "ishelled" ) )
{
return IS_NPC( chkchar ) ? FALSE : mprog_veval( chkchar->pcdata->release_date, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "level" ) )
{
return mprog_veval( get_trust( chkchar ), opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "goldamt" ) )
{
return mprog_veval( chkchar->gold, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "class" ) )
{
if( IS_NPC( chkchar ) )
return mprog_seval( npc_class[chkchar->class], opr, rval, mob );
return mprog_seval( ( char * )class_table[chkchar->class]->who_name, opr, rval, mob );
}
if( !str_cmp( chck, "weight" ) )
{
return mprog_veval( chkchar->carry_weight, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "hostdesc" ) )
{
if( IS_NPC( chkchar ) || !chkchar->desc->host )
return FALSE;
return mprog_seval( chkchar->desc->host, opr, rval, mob );
}
if( !str_cmp( chck, "multi" ) )
{
CHAR_DATA *ch;
lhsvl = 0;
for( ch = first_char; ch; ch = ch->next )
if( !IS_NPC( chkchar ) && !IS_NPC( ch )
&& ch->desc && chkchar->desc && !str_cmp( ch->desc->host, chkchar->desc->host ) )
lhsvl++;
rhsvl = atoi( rval );
if( rhsvl < 0 )
rhsvl = 0;
if( !*opr )
strcpy( opr, "==" );
return mprog_veval( lhsvl, opr, rhsvl, mob );
}
if( !str_cmp( chck, "race" ) )
{
if( IS_NPC( chkchar ) )
return mprog_seval( npc_race[chkchar->race], opr, rval, mob );
return mprog_seval( ( char * )race_table[chkchar->race]->race_name, opr, rval, mob );
}
if( !str_cmp( chck, "morph" ) )
{
if( chkchar->morph == NULL )
return FALSE;
if( chkchar->morph->morph == NULL )
return FALSE;
return mprog_veval( chkchar->morph->morph->vnum, opr, rhsvl, mob );
}
if( !str_cmp( chck, "nuisance" ) )
{
if( IS_NPC( chkchar ) || !chkchar->pcdata->nuisance )
return FALSE;
return mprog_veval( chkchar->pcdata->nuisance->flags, opr, rhsvl, mob );
}
if( !str_cmp( chck, "clan" ) )
{
if( IS_NPC( chkchar ) || !chkchar->pcdata->clan )
return FALSE;
return mprog_seval( chkchar->pcdata->clan->name, opr, rval, mob );
}
/*
* Check added to see if the person isleader of == clan Shaddai
*/
if( !str_cmp( chck, "isleader" ) )
{
CLAN_DATA *temp;
if( IS_NPC( chkchar ) )
return FALSE;
if( ( temp = get_clan( rval ) ) == NULL )
return FALSE;
if( mprog_seval( chkchar->name, opr, temp->leader, mob )
|| mprog_seval( chkchar->name, opr, temp->number1, mob )
|| mprog_seval( chkchar->name, opr, temp->number2, mob ) )
return TRUE;
else
return FALSE;
}
/*
* Is char wearing some eq on a specific wear loc? -- Gorog
*/
if( !str_cmp( chck, "wearing" ) )
{
OBJ_DATA *tobj;
int i = 0;
for( tobj = chkchar->first_carrying; tobj; tobj = tobj->next_content )
{
i++;
if( chkchar == tobj->carried_by && tobj->wear_loc > -1 && !str_cmp( rval, item_w_flags[tobj->wear_loc] ) )
return TRUE;
}
return FALSE;
}
/*
* Is char wearing some specific vnum? -- Gorog
*/
if( !str_cmp( chck, "wearingvnum" ) )
{
OBJ_DATA *tobj;
if( !is_number( rval ) )
return FALSE;
for( tobj = chkchar->first_carrying; tobj; tobj = tobj->next_content )
{
if( chkchar == tobj->carried_by && tobj->wear_loc > -1 && tobj->pIndexData->vnum == atoi( rval ) )
return TRUE;
}
return FALSE;
}
/*
* Is char carrying a specific piece of eq? -- Gorog
*/
if( !str_cmp( chck, "carryingvnum" ) )
{
int vnum;
if( !is_number( rval ) )
return FALSE;
vnum = atoi( rval );
if( !chkchar->first_carrying )
return FALSE;
return ( carryingvnum_visit( chkchar, chkchar->first_carrying, vnum ) );
}
/*
* Check added to see if the person isleader of == clan Gorog
*/
if( !str_cmp( chck, "isclanleader" ) )
{
CLAN_DATA *temp;
if( IS_NPC( chkchar ) )
return FALSE;
if( ( temp = get_clan( rval ) ) == NULL )
return FALSE;
if( mprog_seval( chkchar->name, opr, temp->leader, mob ) )
return TRUE;
else
return FALSE;
}
if( !str_cmp( chck, "isclan1" ) )
{
CLAN_DATA *temp;
if( IS_NPC( chkchar ) )
return FALSE;
if( ( temp = get_clan( rval ) ) == NULL )
return FALSE;
if( mprog_seval( chkchar->name, opr, temp->number1, mob ) )
return TRUE;
else
return FALSE;
}
if( !str_cmp( chck, "isclan2" ) )
{
CLAN_DATA *temp;
if( IS_NPC( chkchar ) )
return FALSE;
if( ( temp = get_clan( rval ) ) == NULL )
return FALSE;
if( mprog_seval( chkchar->name, opr, temp->number2, mob ) )
return TRUE;
else
return FALSE;
}
if( !str_cmp( chck, "council" ) )
{
if( IS_NPC( chkchar ) || !chkchar->pcdata->council )
return FALSE;
return mprog_seval( chkchar->pcdata->council->name, opr, rval, mob );
}
if( !str_cmp( chck, "deity" ) )
{
if( IS_NPC( chkchar ) || !chkchar->pcdata->deity )
return FALSE;
return mprog_seval( chkchar->pcdata->deity->name, opr, rval, mob );
}
if( !str_cmp( chck, "guild" ) )
{
if( IS_NPC( chkchar ) || !IS_GUILDED( chkchar ) )
return FALSE;
return mprog_seval( chkchar->pcdata->clan->name, opr, rval, mob );
}
if( !str_cmp( chck, "clantype" ) )
{
if( IS_NPC( chkchar ) || !chkchar->pcdata->clan )
return FALSE;
return mprog_veval( chkchar->pcdata->clan->clan_type, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "waitstate" ) )
{
if( IS_NPC( chkchar ) || !chkchar->wait )
return FALSE;
return mprog_veval( chkchar->wait, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "asupressed" ) )
{
return mprog_veval( get_timer( chkchar, TIMER_ASUPRESSED ), opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "favor" ) )
{
if( IS_NPC( chkchar ) || !chkchar->pcdata->favor )
return FALSE;
return mprog_veval( chkchar->pcdata->favor, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "hps" ) )
{
return mprog_veval( chkchar->hit, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "mana" ) )
{
return mprog_veval( chkchar->mana, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "str" ) )
{
return mprog_veval( get_curr_str( chkchar ), opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "wis" ) )
{
return mprog_veval( get_curr_wis( chkchar ), opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "int" ) )
{
return mprog_veval( get_curr_int( chkchar ), opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "dex" ) )
{
return mprog_veval( get_curr_dex( chkchar ), opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "con" ) )
{
return mprog_veval( get_curr_con( chkchar ), opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "cha" ) )
{
return mprog_veval( get_curr_cha( chkchar ), opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "lck" ) )
{
return mprog_veval( get_curr_lck( chkchar ), opr, atoi( rval ), mob );
}
}
if( chkobj )
{
if( !str_cmp( chck, "objtype" ) )
{
return mprog_veval( chkobj->item_type, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "leverpos" ) )
{
int isup = FALSE, wantsup = FALSE;
if( chkobj->item_type != ITEM_SWITCH || chkobj->item_type != ITEM_LEVER || chkobj->item_type != ITEM_PULLCHAIN )
return FALSE;
if( IS_SET( obj->value[0], TRIG_UP ) )
isup = TRUE;
if( !str_cmp( rval, "up" ) )
wantsup = TRUE;
return mprog_veval( wantsup, opr, isup, mob );
}
if( !str_cmp( chck, "objval0" ) )
{
return mprog_veval( chkobj->value[0], opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "objval1" ) )
{
return mprog_veval( chkobj->value[1], opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "objval2" ) )
{
return mprog_veval( chkobj->value[2], opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "objval3" ) )
{
return mprog_veval( chkobj->value[3], opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "objval4" ) )
{
return mprog_veval( chkobj->value[4], opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "objval5" ) )
{
return mprog_veval( chkobj->value[5], opr, atoi( rval ), mob );
}
}
/*
* The following checks depend on the fact that cval[1] can only contain
* one character, and that NULL checks were made previously.
*/
if( !str_cmp( chck, "number" ) )
{
if( chkchar )
{
if( !IS_NPC( chkchar ) )
return FALSE;
lhsvl = ( chkchar == mob ) ? chkchar->gold : chkchar->pIndexData->vnum;
return mprog_veval( lhsvl, opr, atoi( rval ), mob );
}
return mprog_veval( chkobj->pIndexData->vnum, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "time" ) )
{
return mprog_veval( time_info.hour, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "questcomplete" ) ) /* new quest shizat */
{ /* usage: if questcomplete($n) == QuestName */
return ( CheckQuestComplete( rval, chkchar ) );
}
if( !str_cmp( chck, "name" ) )
{
if( chkchar )
return mprog_seval( chkchar->name, opr, rval, mob );
return mprog_seval( chkobj->name, opr, rval, mob );
}
if( !str_cmp( chck, "rank" ) ) /* Shaddai */
{
if( chkchar && !IS_NPC( chkchar ) )
return mprog_seval( chkchar->pcdata->rank, opr, rval, mob );
return FALSE;
}
if( !str_cmp( chck, "mortinworld" ) ) /* -- Gorog */
{
DESCRIPTOR_DATA *d;
for( d = first_descriptor; d; d = d->next )
if( d->connected == CON_PLAYING
&& d->character && get_trust( d->character ) < LEVEL_IMMORTAL && nifty_is_name( d->character->name, cvar ) )
return TRUE;
return FALSE;
}
if( !str_cmp( chck, "mortinroom" ) ) /* -- Gorog */
{
CHAR_DATA *ch;
for( ch = mob->in_room->first_person; ch; ch = ch->next_in_room )
if( ( !IS_NPC( ch ) ) && get_trust( ch ) < LEVEL_IMMORTAL && nifty_is_name( ch->name, cvar ) )
return TRUE;
return FALSE;
}
if( !str_cmp( chck, "mortinarea" ) ) /* -- Gorog */
{
CHAR_DATA *ch;
for( ch = first_char; ch; ch = ch->next )
if( ( !IS_NPC( ch ) )
&& ch->in_room->area == mob->in_room->area
&& get_trust( ch ) < LEVEL_IMMORTAL && nifty_is_name( ch->name, cvar ) )
return TRUE;
return FALSE;
}
if( !str_cmp( chck, "mortcount" ) ) /* -- Gorog */
{
CHAR_DATA *tch;
ROOM_INDEX_DATA *room;
int count = 0;
int rvnum = atoi( cvar );
room = get_room_index( rvnum ? rvnum : mob->in_room->vnum );
for( tch = room ? room->first_person : NULL; tch; tch = tch->next_in_room )
if( ( !IS_NPC( tch ) ) && get_trust( tch ) < LEVEL_IMMORTAL )
count++;
return mprog_veval( count, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "mobcount" ) ) /* -- Gorog */
{
CHAR_DATA *tch;
ROOM_INDEX_DATA *room;
int count = -1;
int rvnum = atoi( cvar );
room = get_room_index( rvnum ? rvnum : mob->in_room->vnum );
for( tch = room ? room->first_person : NULL; tch; tch = tch->next_in_room )
if( ( IS_NPC( tch ) ) )
count++;
return mprog_veval( count, opr, atoi( rval ), mob );
}
if( !str_cmp( chck, "charcount" ) ) /* -- Gorog */
{
CHAR_DATA *tch;
ROOM_INDEX_DATA *room;
int count = -1;
int rvnum = atoi( cvar );
room = get_room_index( rvnum ? rvnum : mob->in_room->vnum );
for( tch = room ? room->first_person : NULL; tch; tch = tch->next_in_room )
if( ( ( !IS_NPC( tch ) ) && get_trust( tch ) < LEVEL_IMMORTAL ) || IS_NPC( tch ) ) /* mortal or mob */
count++;
return mprog_veval( count, opr, atoi( rval ), mob );
}
/*
* Ok... all the ifchecks are done, so if we didnt find ours then something
* odd happened. So report the bug and abort the MUDprogram (return error)
*/
progbug( "Unknown ifcheck", mob );
return BERR;
}
#undef isoperator
#undef MAX_IF_ARGS
/* This routine handles the variables for command expansion.
* If you want to add any go right ahead, it should be fairly
* clear how it is done and they are quite easy to do, so you
* can be as creative as you want. The only catch is to check
* that your variables exist before you use them. At the moment,
* using $t when the secondary target refers to an object
* i.e. >prog_act drops~<nl>if ispc($t)<nl>sigh<nl>endif<nl>~<nl>
* probably makes the mud crash (vice versa as well) The cure
* would be to change act() so that vo becomes vict & v_obj.
* but this would require a lot of small changes all over the code.
*/
/*
* There's no reason to make the mud crash when a variable's
* fubared. I added some ifs. I'm willing to trade some
* performance for stability. -Haus
*
* Added char_died and obj_extracted checks -Thoric
*/
void mprog_translate( char ch, char *t, CHAR_DATA * mob, CHAR_DATA * actor, OBJ_DATA * obj, void *vo, CHAR_DATA * rndm )
{
static char *he_she[] = { "it", "he", "she" };
static char *him_her[] = { "it", "him", "her" };
static char *his_her[] = { "its", "his", "her" };
CHAR_DATA *vict = ( CHAR_DATA * ) vo;
OBJ_DATA *v_obj = ( OBJ_DATA * ) vo;
/*
* Fix crash bug :) SHADDAI
*/
if( v_obj && v_obj->serial )
vict = NULL;
else
v_obj = NULL;
*t = '\0';
switch ( ch )
{
case 'i':
if( mob && !char_died( mob ) )
{
if( mob->name )
one_argument( mob->name, t );
}
else
strcpy( t, "someone" );
break;
case 'I':
if( mob && !char_died( mob ) )
{
if( mob->short_descr )
{
strcpy( t, mob->short_descr );
}
else
{
strcpy( t, "someone" );
}
}
else
strcpy( t, "someone" );
break;
case 'n':
if( actor && !char_died( actor ) )
{
if( can_see( mob, actor, FALSE ) )
one_argument( actor->name, t );
if( !IS_NPC( actor ) )
*t = UPPER( *t );
}
else
strcpy( t, "someone" );
break;
case 'N':
if( actor && !char_died( actor ) )
{
if( can_see( mob, actor, FALSE ) )
if( IS_NPC( actor ) )
strcpy( t, actor->short_descr );
else
{
strcpy( t, actor->name );
strcat( t, actor->pcdata->title );
}
else
strcpy( t, "someone" );
}
else
strcpy( t, "someone" );
break;
case 't':
if( vict && !char_died( vict ) )
{
if( can_see( mob, vict, FALSE ) )
one_argument( vict->name, t );
if( !IS_NPC( vict ) )
*t = UPPER( *t );
}
else
strcpy( t, "someone" );
break;
case 'T':
if( vict && !char_died( vict ) )
{
if( can_see( mob, vict, FALSE ) )
if( IS_NPC( vict ) )
strcpy( t, vict->short_descr );
else
{
strcpy( t, vict->name );
strcat( t, " " );
strcat( t, vict->pcdata->title );
}
else
strcpy( t, "someone" );
}
else
strcpy( t, "someone" );
break;
case 'r':
if( rndm && !char_died( rndm ) )
{
if( can_see( mob, rndm, FALSE ) )
{
one_argument( rndm->name, t );
}
if( !IS_NPC( rndm ) )
{
*t = UPPER( *t );
}
}
else
strcpy( t, "someone" );
break;
case 'R':
if( rndm && !char_died( rndm ) )
{
if( can_see( mob, rndm, FALSE ) )
if( IS_NPC( rndm ) )
strcpy( t, rndm->short_descr );
else
{
strcpy( t, rndm->name );
strcat( t, " " );
strcat( t, rndm->pcdata->title );
}
else
strcpy( t, "someone" );
}
else
strcpy( t, "someone" );
break;
case 'e':
if( actor && !char_died( actor ) )
{
can_see( mob, actor, FALSE ) ? strcpy( t, he_she[actor->sex] ) : strcpy( t, "someone" );
}
else
strcpy( t, "it" );
break;
case 'm':
if( actor && !char_died( actor ) )
{
can_see( mob, actor, FALSE ) ? strcpy( t, him_her[actor->sex] ) : strcpy( t, "someone" );
}
else
strcpy( t, "it" );
break;
case 's':
if( actor && !char_died( actor ) )
{
can_see( mob, actor, FALSE ) ? strcpy( t, his_her[actor->sex] ) : strcpy( t, "someone's" );
}
else
strcpy( t, "its'" );
break;
case 'E':
if( vict && !char_died( vict ) )
{
can_see( mob, vict, FALSE ) ? strcpy( t, he_she[vict->sex] ) : strcpy( t, "someone" );
}
else
strcpy( t, "it" );
break;
case 'M':
if( vict && !char_died( vict ) )
{
can_see( mob, vict, FALSE ) ? strcpy( t, him_her[vict->sex] ) : strcpy( t, "someone" );
}
else
strcpy( t, "it" );
break;
case 'S':
if( vict && !char_died( vict ) )
{
can_see( mob, vict, FALSE ) ? strcpy( t, his_her[vict->sex] ) : strcpy( t, "someone's" );
}
else
strcpy( t, "its'" );
break;
case 'j':
if( mob && !char_died( mob ) )
{
strcpy( t, he_she[mob->sex] );
}
else
{
strcpy( t, "it" );
}
break;
case 'k':
if( mob && !char_died( mob ) )
{
strcpy( t, him_her[mob->sex] );
}
else
{
strcpy( t, "it" );
}
break;
case 'l':
if( mob && !char_died( mob ) )
{
strcpy( t, his_her[mob->sex] );
}
else
{
strcpy( t, "it" );
}
break;
case 'J':
if( rndm && !char_died( rndm ) )
{
can_see( mob, rndm, FALSE ) ? strcpy( t, he_she[rndm->sex] ) : strcpy( t, "someone" );
}
else
strcpy( t, "it" );
break;
case 'K':
if( rndm && !char_died( rndm ) )
{
can_see( mob, rndm, FALSE ) ? strcpy( t, him_her[rndm->sex] ) : strcpy( t, "someone's" );
}
else
strcpy( t, "its'" );
break;
case 'L':
if( rndm && !char_died( rndm ) )
{
can_see( mob, rndm, FALSE ) ? strcpy( t, his_her[rndm->sex] ) : strcpy( t, "someone" );
}
else
strcpy( t, "its" );
break;
case 'o':
if( obj && !obj_extracted( obj ) )
{
can_see_obj( mob, obj ) ? one_argument( obj->name, t ) : strcpy( t, "something" );
}
else
strcpy( t, "something" );
break;
case 'O':
if( obj && !obj_extracted( obj ) )
{
can_see_obj( mob, obj ) ? strcpy( t, obj->short_descr ) : strcpy( t, "something" );
}
else
strcpy( t, "something" );
break;
case 'p':
if( v_obj && !obj_extracted( v_obj ) )
{
can_see_obj( mob, v_obj ) ? one_argument( v_obj->name, t ) : strcpy( t, "something" );
}
else
strcpy( t, "something" );
break;
case 'P':
if( v_obj && !obj_extracted( v_obj ) )
{
can_see_obj( mob, v_obj ) ? strcpy( t, v_obj->short_descr ) : strcpy( t, "something" );
}
else
strcpy( t, "something" );
break;
case 'a':
if( obj && !obj_extracted( obj ) )
{
strcpy( t, aoran( obj->name ) );
/*
* switch ( *( obj->name ) )
* {
* case 'a': case 'e': case 'i':
* case 'o': case 'u': strcpy( t, "an" );
* break;
* default: strcpy( t, "a" );
* }
*/
}
else
strcpy( t, "a" );
break;
case 'A':
if( v_obj && !obj_extracted( v_obj ) )
{
strcpy( t, aoran( v_obj->name ) );
}
else
strcpy( t, "a" );
break;
case '$':
strcpy( t, "$" );
break;
default:
progbug( "Bad $var", mob );
break;
}
return;
}
/* The main focus of the MOBprograms. This routine is called
* whenever a trigger is successful. It is responsible for parsing
* the command list and figuring out what to do. However, like all
* complex procedures, everything is farmed out to the other guys.
*
* This function rewritten by Narn for Realms of Despair, Dec/95.
*
*/
void mprog_driver( char *com_list, CHAR_DATA * mob, CHAR_DATA * actor, OBJ_DATA * obj, void *vo, bool single_step )
{
char tmpcmndlst[MAX_STRING_LENGTH];
char *command_list;
char *cmnd;
CHAR_DATA *rndm = NULL;
CHAR_DATA *vch = NULL;
int count = 0;
int count2 = 0;
int ignorelevel = 0;
int iflevel, result;
bool ifstate[MAX_IFS][DO_ELSE + 1];
static int prog_nest;
MPSLEEP_DATA *mpsleep = NULL;
char arg[MAX_INPUT_LENGTH];
if (IS_AFFECTED( mob, AFF_CHARM ))
return;
/*
* Next couple of checks stop program looping. -- Altrag
*/
if( mob == actor )
{
progbug( "triggering oneself.", mob );
return;
}
if( ++prog_nest > MAX_PROG_NEST )
{
progbug( "max_prog_nest exceeded.", mob );
--prog_nest;
return;
}
/*
* Make sure all ifstate bools are set to FALSE
*/
for( iflevel = 0; iflevel < MAX_IFS; iflevel++ )
{
for( count = 0; count < DO_ELSE; count++ )
{
ifstate[iflevel][count] = FALSE;
}
}
iflevel = 0;
/*
* get a random visible player who is in the room with the mob.
*
* If there isn't a random player in the room, rndm stays NULL.
* If you do a $r, $R, $j, or $k with rndm = NULL, you'll crash
* in mprog_translate.
*
* Adding appropriate error checking in mprog_translate.
* -Haus
*
* This used to ignore players MAX_LEVEL - 3 and higher (standard
* Merc has 4 immlevels). Thought about changing it to ignore all
* imms, but decided to just take it out. If the mob can see you,
* you may be chosen as the random player. -Narn
*
*/
count = 0;
for( vch = mob->in_room->first_person; vch; vch = vch->next_in_room )
if( !IS_NPC( vch ) && can_see( mob, vch, FALSE ) )
{
if( number_range( 0, count ) == 0 )
rndm = vch;
count++;
}
strcpy( tmpcmndlst, com_list );
command_list = tmpcmndlst;
/*
* mpsleep - Restore the environment -rkb
*/
if( current_mpsleep )
{
ignorelevel = current_mpsleep->ignorelevel;
iflevel = current_mpsleep->iflevel;
if( single_step )
mob->mpscriptpos = 0;
for( count = 0; count < MAX_IFS; count++ )
{
for( count2 = 0; count2 < DO_ELSE; count2++ )
ifstate[count][count2] = current_mpsleep->ifstate[count][count2];
}
current_mpsleep = NULL;
}
if( single_step )
{
if( mob->mpscriptpos > strlen( tmpcmndlst ) )
mob->mpscriptpos = 0;
else
command_list += mob->mpscriptpos;
if( *command_list == '\0' )
{
command_list = tmpcmndlst;
mob->mpscriptpos = 0;
}
}
/*
* From here on down, the function is all mine. The original code
* did not support nested ifs, so it had to be redone. The max
* logiclevel (MAX_IFS) is defined at the beginning of this file,
* use it to increase/decrease max allowed nesting. -Narn
*/
while( TRUE )
{
/*
* With these two lines, cmnd becomes the current line from the prog,
* and command_list becomes everything after that line.
*/
cmnd = command_list;
command_list = mprog_next_command( command_list );
/*
* Are we at the end?
*/
if( cmnd[0] == '\0' )
{
if( ifstate[iflevel][IN_IF] || ifstate[iflevel][IN_ELSE] )
{
progbug( "Missing endif", mob );
}
--prog_nest;
return;
}
/*
* mpsleep - Check if we should sleep -rkb
*/
if( !str_prefix( "mpsleep", cmnd ) )
{
CREATE( mpsleep, MPSLEEP_DATA, 1 );
/*
* State variables
*/
mpsleep->ignorelevel = ignorelevel;
mpsleep->iflevel = iflevel;
for( count = 0; count < MAX_IFS; count++ )
{
for( count2 = 0; count2 < DO_ELSE; count2++ )
{
mpsleep->ifstate[count][count2] = ifstate[count][count2];
}
}
/*
* Driver arguments
*/
mpsleep->com_list = STRALLOC( command_list );
mpsleep->mob = mob;
mpsleep->actor = actor;
mpsleep->obj = obj;
mpsleep->vo = vo;
mpsleep->single_step = single_step;
/*
* Time to sleep
*/
cmnd = one_argument( cmnd, arg );
cmnd = one_argument( cmnd, arg );
if( arg[0] == '\0' )
mpsleep->timer = 4;
else
mpsleep->timer = atoi( arg );
if( mpsleep->timer < 1 )
{
progbug( "mpsleep - bad arg, using default", mob );
mpsleep->timer = 4;
}
/*
* Save type of prog, room, object or mob
*/
if( mpsleep->mob->pIndexData->vnum == 3 )
{
if( !str_prefix( "Room", mpsleep->mob->description ) )
{
mpsleep->type = MP_ROOM;
mpsleep->room = mpsleep->mob->in_room;
}
else if( !str_prefix( "Object", mpsleep->mob->description ) )
mpsleep->type = MP_OBJ;
}
else
mpsleep->type = MP_MOB;
LINK( mpsleep, first_mpsleep, last_mpsleep, next, prev );
--prog_nest;
return;
}
cmnd = strip_tilde( cmnd );
/*
* Evaluate/execute the command, check what happened.
*/
result = mprog_do_command( cmnd, mob, actor, obj, vo, rndm,
( ifstate[iflevel][IN_IF] && !ifstate[iflevel][DO_IF] )
|| ( ifstate[iflevel][IN_ELSE] && !ifstate[iflevel][DO_ELSE] ), ( ignorelevel > 0 ) );
/*
* Script prog support -Thoric
*/
if( single_step )
{
mob->mpscriptpos = command_list - tmpcmndlst;
--prog_nest;
return;
}
/*
* This is the complicated part. Act on the returned value from
* mprog_do_command according to the current logic state.
*/
switch ( result )
{
case COMMANDOK:
#ifdef DEBUG
log_string( "COMMANDOK" );
#endif
/*
* Ok, this one's a no-brainer.
*/
continue;
break;
case IFTRUE:
#ifdef DEBUG
log_string( "IFTRUE" );
#endif
/*
* An if was evaluated and found true. Note that we are in an
* if section and that we want to execute it.
*/
iflevel++;
if( iflevel == MAX_IFS )
{
progbug( "Maximum nested ifs exceeded", mob );
--prog_nest;
return;
}
ifstate[iflevel][IN_IF] = TRUE;
ifstate[iflevel][DO_IF] = TRUE;
break;
case IFFALSE:
#ifdef DEBUG
log_string( "IFFALSE" );
#endif
/*
* An if was evaluated and found false. Note that we are in an
* if section and that we don't want to execute it unless we find
* an or that evaluates to true.
*/
iflevel++;
if( iflevel == MAX_IFS )
{
progbug( "Maximum nested ifs exceeded", mob );
--prog_nest;
return;
}
ifstate[iflevel][IN_IF] = TRUE;
ifstate[iflevel][DO_IF] = FALSE;
break;
case ORTRUE:
#ifdef DEBUG
log_string( "ORTRUE" );
#endif
/*
* An or was evaluated and found true. We should already be in an
* if section, so note that we want to execute it.
*/
if( !ifstate[iflevel][IN_IF] )
{
progbug( "Unmatched or", mob );
--prog_nest;
return;
}
ifstate[iflevel][DO_IF] = TRUE;
break;
case ORFALSE:
#ifdef DEBUG
log_string( "ORFALSE" );
#endif
/*
* An or was evaluated and found false. We should already be in an
* if section, and we don't need to do much. If the if was true or
* there were/will be other ors that evaluate(d) to true, they'll set
* do_if to true.
*/
if( !ifstate[iflevel][IN_IF] )
{
progbug( "Unmatched or", mob );
--prog_nest;
return;
}
continue;
break;
case FOUNDELSE:
#ifdef DEBUG
log_string( "FOUNDELSE" );
#endif
/*
* Found an else. Make sure we're in an if section, bug out if not.
* If this else is not one that we wish to ignore, note that we're now
* in an else section, and look at whether or not we executed the if
* section to decide whether to execute the else section. Ca marche
* bien.
*/
if( ignorelevel > 0 )
continue;
if( ifstate[iflevel][IN_ELSE] )
{
progbug( "Found else in an else section", mob );
--prog_nest;
return;
}
if( !ifstate[iflevel][IN_IF] )
{
progbug( "Unmatched else", mob );
--prog_nest;
return;
}
ifstate[iflevel][IN_ELSE] = TRUE;
ifstate[iflevel][DO_ELSE] = !ifstate[iflevel][DO_IF];
ifstate[iflevel][IN_IF] = FALSE;
ifstate[iflevel][DO_IF] = FALSE;
break;
case FOUNDENDIF:
#ifdef DEBUG
log_string( "FOUNDENDIF" );
#endif
/*
* Hmm, let's see... FOUNDENDIF must mean that we found an endif.
* So let's make sure we were expecting one, return if not. If this
* endif matches the if or else that we're executing, note that we are
* now no longer executing an if. If not, keep track of what we're
* ignoring.
*/
if( !( ifstate[iflevel][IN_IF] || ifstate[iflevel][IN_ELSE] ) )
{
progbug( "Unmatched endif", mob );
--prog_nest;
return;
}
if( ignorelevel > 0 )
{
ignorelevel--;
continue;
}
ifstate[iflevel][IN_IF] = FALSE;
ifstate[iflevel][DO_IF] = FALSE;
ifstate[iflevel][IN_ELSE] = FALSE;
ifstate[iflevel][DO_ELSE] = FALSE;
iflevel--;
break;
case IFIGNORED:
#ifdef DEBUG
log_string( "IFIGNORED" );
#endif
if( !( ifstate[iflevel][IN_IF] || ifstate[iflevel][IN_ELSE] ) )
{
progbug( "Parse error, ignoring if while not in if or else", mob );
--prog_nest;
return;
}
ignorelevel++;
break;
case ORIGNORED:
#ifdef DEBUG
log_string( "ORIGNORED" );
#endif
if( !( ifstate[iflevel][IN_IF] || ifstate[iflevel][IN_ELSE] ) )
{
progbug( "Unmatched or", mob );
--prog_nest;
return;
}
if( ignorelevel == 0 )
{
progbug( "Parse error, mistakenly ignoring or", mob );
--prog_nest;
return;
}
break;
case BERR:
#ifdef DEBUG
log_string( "BERR" );
#endif
--prog_nest;
return;
break;
}
}
--prog_nest;
return;
}
/* This function replaces mprog_process_cmnd. It is called from
* mprog_driver, once for each line in a mud prog. This function
* checks what the line is, executes if/or checks and calls interpret
* to perform the the commands. Written by Narn, Dec 95.
*/
int mprog_do_command( char *cmnd, CHAR_DATA * mob, CHAR_DATA * actor,
OBJ_DATA * obj, void *vo, CHAR_DATA * rndm, bool ignore, bool ignore_ors )
{
char firstword[MAX_INPUT_LENGTH];
char *ifcheck;
char buf[MAX_INPUT_LENGTH];
char tmp[MAX_INPUT_LENGTH];
char *point, *str, *i;
int validif, vnum;
/*
* Isolate the first word of the line, it gives us a clue what
* we want to do.
*/
ifcheck = one_argument( cmnd, firstword );
if( !str_cmp( firstword, "if" ) )
{
/*
* Ok, we found an if. According to the boolean 'ignore', either
* ignore the ifcheck and report that back to mprog_driver or do
* the ifcheck and report whether it was successful.
*/
if( ignore )
return IFIGNORED;
else
validif = mprog_do_ifcheck( ifcheck, mob, actor, obj, vo, rndm );
if( validif == 1 )
return IFTRUE;
if( validif == 0 )
return IFFALSE;
return BERR;
}
if( !str_cmp( firstword, "or" ) )
{
/*
* Same behavior as with ifs, but use the boolean 'ignore_ors' to
* decide which way to go.
*/
if( ignore_ors )
return ORIGNORED;
else
validif = mprog_do_ifcheck( ifcheck, mob, actor, obj, vo, rndm );
if( validif == 1 )
return ORTRUE;
if( validif == 0 )
return ORFALSE;
return BERR;
}
/*
* For else and endif, just report back what we found. Mprog_driver
* keeps track of logiclevels.
*/
if( !str_cmp( firstword, "else" ) )
{
return FOUNDELSE;
}
if( !str_cmp( firstword, "endif" ) )
{
return FOUNDENDIF;
}
/*
* Ok, didn't find an if, an or, an else or an endif.
* If the command is in an if or else section that is not to be
* performed, the boolean 'ignore' is set to true and we just
* return. If not, we try to execute the command.
*/
if( ignore )
return COMMANDOK;
/*
* If the command is 'break', that's all folks.
*/
if( !str_cmp( firstword, "break" ) )
return BERR;
vnum = mob->pIndexData->vnum;
point = buf;
str = cmnd;
/*
* This chunk of code taken from mprog_process_cmnd.
*/
while( *str != '\0' )
{
if( *str != '$' )
{
*point++ = *str++;
continue;
}
str++;
mprog_translate( *str, tmp, mob, actor, obj, vo, rndm );
i = tmp;
++str;
while( ( *point = *i ) != '\0' )
++point, ++i;
}
*point = '\0';
interpret( mob, buf );
/*
* If the mob is mentally unstable and does things like fireball
* itself, let's make sure it's still alive.
*/
if( char_died( mob ) )
{
bug( "Mob died while executing program, vnum %d.", vnum );
return BERR;
}
return COMMANDOK;
}
/***************************************************************************
* Global function code and brief comments.
*/
/* See if there's any mud programs waiting to be continued -rkb */
void mpsleep_update( )
{
MPSLEEP_DATA *mpsleep;
MPSLEEP_DATA *tmpMpsleep;
bool delete_it;
mpsleep = first_mpsleep;
while( mpsleep )
{
delete_it = FALSE;
if( mpsleep->mob )
delete_it = char_died( mpsleep->mob );
if( mpsleep->actor && !delete_it )
delete_it = char_died( mpsleep->actor );
if( mpsleep->obj && !delete_it )
delete_it = obj_extracted( mpsleep->obj );
if( delete_it )
{
log_string( "mpsleep_update - Deleting expired prog." );
tmpMpsleep = mpsleep;
mpsleep = mpsleep->next;
STRFREE( tmpMpsleep->com_list );
UNLINK( tmpMpsleep, first_mpsleep, last_mpsleep, next, prev );
DISPOSE( tmpMpsleep );
continue;
}
mpsleep = mpsleep->next;
}
mpsleep = first_mpsleep;
while( mpsleep ) /* Find progs to continue */
{
if( --mpsleep->timer <= 0 )
{
current_mpsleep = mpsleep;
if( mpsleep->type == MP_ROOM )
rset_supermob( mpsleep->room );
else if( mpsleep->type == MP_OBJ )
set_supermob( mpsleep->obj );
mprog_driver( mpsleep->com_list, mpsleep->mob, mpsleep->actor, mpsleep->obj, mpsleep->vo, mpsleep->single_step );
release_supermob( );
tmpMpsleep = mpsleep;
mpsleep = mpsleep->next;
STRFREE( tmpMpsleep->com_list );
UNLINK( tmpMpsleep, first_mpsleep, last_mpsleep, next, prev );
DISPOSE( tmpMpsleep );
continue;
}
mpsleep = mpsleep->next;
}
}
bool mprog_keyword_check( const char *argu, const char *argl )
{
char word[MAX_INPUT_LENGTH];
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
int i;
char *arg, *arglist;
char *start, *end;
strcpy( arg1, strlower( argu ) );
arg = arg1;
strcpy( arg2, strlower( argl ) );
arglist = arg2;
for( i = 0; i < strlen( arglist ); i++ )
arglist[i] = LOWER( arglist[i] );
for( i = 0; i < strlen( arg ); i++ )
arg[i] = LOWER( arg[i] );
if( ( arglist[0] == 'p' ) && ( arglist[1] == ' ' ) )
{
arglist += 2;
while( ( start = strstr( arg, arglist ) ) )
if( ( start == arg || *( start - 1 ) == ' ' )
&& ( *( end = start + strlen( arglist ) ) == ' ' || *end == '\n' || *end == '\r' || *end == '\0' ) )
return TRUE;
else
arg = start + 1;
}
else
{
arglist = one_argument( arglist, word );
for( ; word[0] != '\0'; arglist = one_argument( arglist, word ) )
while( ( start = strstr( arg, word ) ) )
if( ( start == arg || *( start - 1 ) == ' ' )
&& ( *( end = start + strlen( word ) ) == ' ' || *end == '\n' || *end == '\r' || *end == '\0' ) )
return TRUE;
else
arg = start + 1;
}
/*
* bug( "don't match" );
*/
return FALSE;
}
/* The next two routines are the basic trigger types. Either trigger
* on a certain percent, or trigger on a keyword or word phrase.
* To see how this works, look at the various trigger routines..
*/
void mprog_wordlist_check( char *arg, CHAR_DATA * mob, CHAR_DATA * actor, OBJ_DATA * obj, void *vo, int type )
{
char temp1[MAX_STRING_LENGTH];
char temp2[MAX_INPUT_LENGTH];
char word[MAX_INPUT_LENGTH];
MPROG_DATA *mprg;
char *list;
char *start;
char *dupl;
char *end;
int i;
for( mprg = mob->pIndexData->mudprogs; mprg; mprg = mprg->next )
if( mprg->type == type )
{
strcpy( temp1, mprg->arglist );
list = temp1;
for( i = 0; i < strlen( list ); i++ )
list[i] = LOWER( list[i] );
strcpy( temp2, arg );
dupl = temp2;
for( i = 0; i < strlen( dupl ); i++ )
dupl[i] = LOWER( dupl[i] );
if( ( list[0] == 'p' ) && ( list[1] == ' ' ) )
{
list += 2;
while( ( start = strstr( dupl, list ) ) )
if( ( start == dupl || *( start - 1 ) == ' ' )
&& ( *( end = start + strlen( list ) ) == ' ' || *end == '\n' || *end == '\r' || *end == '\0' ) )
{
mprog_driver( mprg->comlist, mob, actor, obj, vo, FALSE );
break;
}
else
dupl = start + 1;
}
else
{
list = one_argument( list, word );
for( ; word[0] != '\0'; list = one_argument( list, word ) )
while( ( start = strstr( dupl, word ) ) )
if( ( start == dupl || *( start - 1 ) == ' ' )
&& ( *( end = start + strlen( word ) ) == ' ' || *end == '\n' || *end == '\r' || *end == '\0' ) )
{
mprog_driver( mprg->comlist, mob, actor, obj, vo, FALSE );
break;
}
else
dupl = start + 1;
}
}
return;
}
void mprog_percent_check( CHAR_DATA * mob, CHAR_DATA * actor, OBJ_DATA * obj, void *vo, int type )
{
MPROG_DATA *mprg;
for( mprg = mob->pIndexData->mudprogs; mprg; mprg = mprg->next )
if( ( mprg->type == type ) && ( number_percent( ) <= atoi( mprg->arglist ) ) )
{
mprog_driver( mprg->comlist, mob, actor, obj, vo, FALSE );
if( type != GREET_PROG && type != ALL_GREET_PROG )
break;
}
return;
}
void mprog_time_check( CHAR_DATA * mob, CHAR_DATA * actor, OBJ_DATA * obj, void *vo, int type )
{
MPROG_DATA *mprg;
bool trigger_time;
for( mprg = mob->pIndexData->mudprogs; mprg; mprg = mprg->next )
{
trigger_time = ( time_info.hour == atoi( mprg->arglist ) );
if( !trigger_time )
{
if( mprg->triggered )
mprg->triggered = FALSE;
continue;
}
if( ( mprg->type == type ) && ( ( !mprg->triggered ) || ( mprg->type == HOUR_PROG ) ) )
{
mprg->triggered = TRUE;
mprog_driver( mprg->comlist, mob, actor, obj, vo, FALSE );
}
}
return;
}
void mob_act_add( CHAR_DATA * mob )
{
struct act_prog_data *runner, *tmp_mal;
for( runner = mob_act_list; runner; runner = runner->next )
if( runner->vo == mob )
return;
CREATE( runner, struct act_prog_data, 1 );
runner->vo = mob;
runner->next = NULL;
/*
* The head of the list is being changed in
* aggr_update, So append to the end of the list
* instead. -Druid
*/
if( mob_act_list )
{
tmp_mal = mob_act_list;
while( tmp_mal->next != NULL )
tmp_mal = tmp_mal->next;
/*
* put at the end
*/
tmp_mal->next = runner;
}
else
mob_act_list = runner;
}
/* The triggers.. These are really basic, and since most appear only
* once in the code (hmm. i think they all do) it would be more efficient
* to substitute the code in and make the mprog_xxx_check routines global.
* However, they are all here in one nice place at the moment to make it
* easier to see what they look like. If you do substitute them back in,
* make sure you remember to modify the variable names to the ones in the
* trigger calls.
*/
void mprog_act_trigger( char *buf, CHAR_DATA * mob, CHAR_DATA * ch, OBJ_DATA * obj, void *vo )
{
MPROG_ACT_LIST *tmp_act, *tmp_mal;
MPROG_DATA *mprg;
bool found = FALSE;
if( IS_NPC( mob ) && HAS_PROG( mob->pIndexData, ACT_PROG ) )
{
/*
* Don't let a mob trigger itself, nor one instance of a mob
* trigger another instance.
*/
if( IS_NPC( ch ) && ch->pIndexData == mob->pIndexData )
return;
/*
* make sure this is a matching trigger
*/
for( mprg = mob->pIndexData->mudprogs; mprg; mprg = mprg->next )
if( mprg->type == ACT_PROG && mprog_keyword_check( buf, mprg->arglist ) )
{
found = TRUE;
break;
}
if( !found )
return;
CREATE( tmp_act, MPROG_ACT_LIST, 1 );
/*
* Losing the head of the list -Druid
*/
if( mob->mpactnum > 0 )
{
tmp_mal = mob->mpact;
while( tmp_mal->next != NULL )
tmp_mal = tmp_mal->next;
/*
* Put at the end
*/
tmp_mal->next = tmp_act;
}
else
mob->mpact = tmp_act;
tmp_act->next = NULL;
tmp_act->buf = str_dup( buf );
tmp_act->ch = ch;
tmp_act->obj = obj;
tmp_act->vo = vo;
mob->mpactnum++;
mob_act_add( mob );
}
return;
}
void mprog_bribe_trigger( CHAR_DATA * mob, CHAR_DATA * ch, int amount )
{
char buf[MAX_STRING_LENGTH];
MPROG_DATA *mprg;
OBJ_DATA *obj;
if( IS_NPC( mob ) && can_see( mob, ch, FALSE ) && HAS_PROG( mob->pIndexData, BRIBE_PROG ) )
{
/*
* Don't let a mob trigger itself, nor one instance of a mob
* trigger another instance.
*/
if( IS_NPC( ch ) && ch->pIndexData == mob->pIndexData )
return;
obj = create_object( get_obj_index( OBJ_VNUM_MONEY_SOME ), 0 );
sprintf( buf, obj->short_descr, amount );
STRFREE( obj->short_descr );
obj->short_descr = STRALLOC( buf );
obj->value[0] = amount;
obj = obj_to_char( obj, mob );
mob->gold -= amount;
for( mprg = mob->pIndexData->mudprogs; mprg; mprg = mprg->next )
if( ( mprg->type == BRIBE_PROG ) && ( amount >= atoi( mprg->arglist ) ) )
{
mprog_driver( mprg->comlist, mob, ch, obj, NULL, FALSE );
break;
}
}
return;
}
void mprog_death_trigger( CHAR_DATA * killer, CHAR_DATA * mob )
{
if( IS_NPC( mob ) && killer != mob && HAS_PROG( mob->pIndexData, DEATH_PROG ) )
{
mob->position = POS_STANDING;
mprog_percent_check( mob, killer, NULL, NULL, DEATH_PROG );
mob->position = POS_DEAD;
}
death_cry( mob );
return;
}
void mprog_entry_trigger( CHAR_DATA * mob )
{
if( IS_NPC( mob ) && HAS_PROG( mob->pIndexData, ENTRY_PROG ) )
mprog_percent_check( mob, NULL, NULL, NULL, ENTRY_PROG );
return;
}
void mprog_fight_trigger( CHAR_DATA * mob, CHAR_DATA * ch )
{
if( IS_NPC( mob ) && HAS_PROG( mob->pIndexData, FIGHT_PROG ) )
mprog_percent_check( mob, ch, NULL, NULL, FIGHT_PROG );
return;
}
void mprog_give_trigger( CHAR_DATA * mob, CHAR_DATA * ch, OBJ_DATA * obj )
{
char buf[MAX_INPUT_LENGTH];
MPROG_DATA *mprg;
if( IS_NPC( mob ) && can_see( mob, ch, FALSE ) && HAS_PROG( mob->pIndexData, GIVE_PROG ) )
{
/*
* Don't let a mob trigger itself, nor one instance of a mob
* trigger another instance.
*/
if( IS_NPC( ch ) && ch->pIndexData == mob->pIndexData )
return;
for( mprg = mob->pIndexData->mudprogs; mprg; mprg = mprg->next )
{
one_argument( mprg->arglist, buf );
if( mprg->type == GIVE_PROG && ( !str_cmp( obj->name, mprg->arglist ) || !str_cmp( "all", buf ) ) )
{
mprog_driver( mprg->comlist, mob, ch, obj, NULL, FALSE );
break;
}
}
}
return;
}
void mprog_greet_trigger( CHAR_DATA * ch )
{
CHAR_DATA *vmob, *vmob_next;
#ifdef DEBUG
char buf[MAX_STRING_LENGTH];
sprintf( buf, "mprog_greet_trigger -> %s", ch->name );
log_string( buf );
#endif
for( vmob = ch->in_room->first_person; vmob; vmob = vmob_next )
{
vmob_next = vmob->next_in_room;
if( !IS_NPC( vmob ) || !can_see( vmob, ch, FALSE ) || vmob->fighting || !IS_AWAKE( vmob ) )
continue;
/*
* Don't let a mob trigger itself, nor one instance of a mob
* trigger another instance.
*/
if( IS_NPC( ch ) && ch->pIndexData == vmob->pIndexData )
continue;
if( HAS_PROG( vmob->pIndexData, GREET_PROG ) )
mprog_percent_check( vmob, ch, NULL, NULL, GREET_PROG );
else if( HAS_PROG( vmob->pIndexData, ALL_GREET_PROG ) )
mprog_percent_check( vmob, ch, NULL, NULL, ALL_GREET_PROG );
}
return;
}
void mprog_hitprcnt_trigger( CHAR_DATA * mob, CHAR_DATA * ch )
{
MPROG_DATA *mprg;
if( IS_NPC( mob ) && HAS_PROG( mob->pIndexData, HITPRCNT_PROG ) )
{
for( mprg = mob->pIndexData->mudprogs; mprg; mprg = mprg->next )
if( mprg->type == HITPRCNT_PROG && ( 100 * mob->hit / mob->max_hit ) < atoi( mprg->arglist ) )
{
mprog_driver( mprg->comlist, mob, ch, NULL, NULL, FALSE );
break;
}
}
return;
}
void mprog_random_trigger( CHAR_DATA * mob )
{
if( HAS_PROG( mob->pIndexData, RAND_PROG ) )
mprog_percent_check( mob, NULL, NULL, NULL, RAND_PROG );
}
void mprog_time_trigger( CHAR_DATA * mob )
{
if( HAS_PROG( mob->pIndexData, TIME_PROG ) )
mprog_time_check( mob, NULL, NULL, NULL, TIME_PROG );
}
void mprog_hour_trigger( CHAR_DATA * mob )
{
if( HAS_PROG( mob->pIndexData, HOUR_PROG ) )
mprog_time_check( mob, NULL, NULL, NULL, HOUR_PROG );
}
void mprog_speech_trigger( char *txt, CHAR_DATA * actor )
{
CHAR_DATA *vmob;
for( vmob = actor->in_room->first_person; vmob; vmob = vmob->next_in_room )
{
if( IS_NPC( vmob ) && HAS_PROG( vmob->pIndexData, SPEECH_PROG ) )
{
if( IS_NPC( actor ) && actor->pIndexData == vmob->pIndexData )
continue;
mprog_wordlist_check( txt, vmob, actor, NULL, NULL, SPEECH_PROG );
}
}
}
void mprog_script_trigger( CHAR_DATA * mob )
{
MPROG_DATA *mprg;
if( HAS_PROG( mob->pIndexData, SCRIPT_PROG ) )
for( mprg = mob->pIndexData->mudprogs; mprg; mprg = mprg->next )
if( mprg->type == SCRIPT_PROG
&& ( mprg->arglist[0] == '\0' || mob->mpscriptpos != 0 || atoi( mprg->arglist ) == time_info.hour ) )
mprog_driver( mprg->comlist, mob, NULL, NULL, NULL, TRUE );
}
void oprog_script_trigger( OBJ_DATA * obj )
{
MPROG_DATA *mprg;
if( HAS_PROG( obj->pIndexData, SCRIPT_PROG ) )
for( mprg = obj->pIndexData->mudprogs; mprg; mprg = mprg->next )
if( mprg->type == SCRIPT_PROG )
{
if( mprg->arglist[0] == '\0' || obj->mpscriptpos != 0 || atoi( mprg->arglist ) == time_info.hour )
{
set_supermob( obj );
mprog_driver( mprg->comlist, supermob, NULL, NULL, NULL, TRUE );
obj->mpscriptpos = supermob->mpscriptpos;
release_supermob( );
}
}
return;
}
void rprog_script_trigger( ROOM_INDEX_DATA * room )
{
MPROG_DATA *mprg;
if( HAS_PROG( room, SCRIPT_PROG ) )
for( mprg = room->mudprogs; mprg; mprg = mprg->next )
if( mprg->type == SCRIPT_PROG )
{
if( mprg->arglist[0] == '\0' || room->mpscriptpos != 0 || atoi( mprg->arglist ) == time_info.hour )
{
rset_supermob( room );
mprog_driver( mprg->comlist, supermob, NULL, NULL, NULL, TRUE );
room->mpscriptpos = supermob->mpscriptpos;
release_supermob( );
}
}
return;
}
/*
* Mudprogram additions begin here
*/
void set_supermob( OBJ_DATA * obj )
{
ROOM_INDEX_DATA *room;
OBJ_DATA *in_obj;
CHAR_DATA *mob;
char buf[200];
if( !supermob )
supermob = create_mobile( get_mob_index( 3 ) );
mob = supermob; /* debugging */
if( !obj )
return;
for( in_obj = obj; in_obj->in_obj; in_obj = in_obj->in_obj )
;
if( in_obj->carried_by )
{
room = in_obj->carried_by->in_room;
}
else
{
room = obj->in_room;
}
if( !room )
return;
if( supermob->short_descr )
STRFREE( supermob->short_descr );
supermob->short_descr = QUICKLINK( obj->short_descr );
supermob->mpscriptpos = obj->mpscriptpos;
/*
* Added by Jenny to allow bug messages to show the vnum
* of the object, and not just supermob's vnum
*/
sprintf( buf, "Object #%d", obj->pIndexData->vnum );
STRFREE( supermob->description );
supermob->description = STRALLOC( buf );
if( room != NULL )
{
char_from_room( supermob );
char_to_room( supermob, room );
if( IS_OBJ_STAT( obj, ITEM_ONMAP ) )
{
SET_ACT_FLAG( supermob, ACT_ONMAP );
supermob->map = obj->map;
supermob->x = obj->x;
supermob->y = obj->y;
}
}
}
void release_supermob( )
{
char_from_room( supermob );
char_to_room( supermob, get_room_index( 3 ) );
if( IS_ACT_FLAG( supermob, ACT_ONMAP ) )
{
REMOVE_ACT_FLAG( supermob, ACT_ONMAP );
supermob->map = -1;
supermob->x = -1;
supermob->y = -1;
}
}
bool oprog_percent_check( CHAR_DATA * mob, CHAR_DATA * actor, OBJ_DATA * obj, void *vo, int type )
{
MPROG_DATA *mprg;
bool executed = FALSE;
for( mprg = obj->pIndexData->mudprogs; mprg; mprg = mprg->next )
if( mprg->type == type && ( number_percent( ) <= atoi( mprg->arglist ) ) )
{
executed = TRUE;
mprog_driver( mprg->comlist, mob, actor, obj, vo, FALSE );
if( type != GREET_PROG )
break;
}
return executed;
}
/*
* Triggers follow
*/
/*
* Hold on this
*
void oprog_act_trigger( CHAR_DATA *ch, OBJ_DATA *obj )
{
set_supermob( obj );
if ( HAS_PROG(obj->pIndexData, ACT_PROG) )
oprog_percent_check( supermob, ch, obj, NULL, ACT_PROG );
release_supermob();
return;
}
*
*
*/
void oprog_greet_trigger( CHAR_DATA * ch )
{
OBJ_DATA *vobj;
for( vobj = ch->in_room->first_content; vobj; vobj = vobj->next_content )
if( HAS_PROG( vobj->pIndexData, GREET_PROG ) )
{
set_supermob( vobj ); /* not very efficient to do here */
oprog_percent_check( supermob, ch, vobj, NULL, GREET_PROG );
release_supermob( );
}
}
void oprog_speech_trigger( char *txt, CHAR_DATA * ch )
{
OBJ_DATA *vobj;
/*
* supermob is set and released in oprog_wordlist_check
*/
for( vobj = ch->in_room->first_content; vobj; vobj = vobj->next_content )
if( HAS_PROG( vobj->pIndexData, SPEECH_PROG ) )
oprog_wordlist_check( txt, supermob, ch, vobj, NULL, SPEECH_PROG, vobj );
return;
}
/*
* Called at top of obj_update
* make sure to put an if(!obj) continue
* after it
*/
void oprog_random_trigger( OBJ_DATA * obj )
{
if( HAS_PROG( obj->pIndexData, RAND_PROG ) )
{
set_supermob( obj );
oprog_percent_check( supermob, NULL, obj, NULL, RAND_PROG );
release_supermob( );
}
}
/*
* in wear_obj, between each successful equip_char
* the subsequent return
*/
void oprog_wear_trigger( CHAR_DATA * ch, OBJ_DATA * obj )
{
if( HAS_PROG( obj->pIndexData, WEAR_PROG ) )
{
set_supermob( obj );
oprog_percent_check( supermob, ch, obj, NULL, WEAR_PROG );
release_supermob( );
}
}
bool oprog_use_trigger( CHAR_DATA * ch, OBJ_DATA * obj, CHAR_DATA * vict, OBJ_DATA * targ, void *vo )
{
bool executed = FALSE;
if( HAS_PROG( obj->pIndexData, USE_PROG ) )
{
set_supermob( obj );
if( obj->item_type == ITEM_STAFF || obj->item_type == ITEM_WAND || obj->item_type == ITEM_SCROLL )
{
if( vict )
executed = oprog_percent_check( supermob, ch, obj, vict, USE_PROG );
else
executed = oprog_percent_check( supermob, ch, obj, targ, USE_PROG );
}
else
executed = oprog_percent_check( supermob, ch, obj, NULL, USE_PROG );
release_supermob( );
}
return executed;
}
/*
* call in remove_obj, right after unequip_char
* do a if(!ch) return right after, and return TRUE (?)
* if !ch
*/
void oprog_remove_trigger( CHAR_DATA * ch, OBJ_DATA * obj )
{
if( HAS_PROG( obj->pIndexData, REMOVE_PROG ) )
{
set_supermob( obj );
oprog_percent_check( supermob, ch, obj, NULL, REMOVE_PROG );
release_supermob( );
}
}
/*
* call in do_sac, right before extract_obj
*/
void oprog_sac_trigger( CHAR_DATA * ch, OBJ_DATA * obj )
{
if( HAS_PROG( obj->pIndexData, SAC_PROG ) )
{
set_supermob( obj );
oprog_percent_check( supermob, ch, obj, NULL, SAC_PROG );
release_supermob( );
}
}
/*
* call in do_get, right before check_for_trap
* do a if(!ch) return right after
*/
void oprog_get_trigger( CHAR_DATA * ch, OBJ_DATA * obj )
{
if( HAS_PROG( obj->pIndexData, GET_PROG ) )
{
set_supermob( obj );
oprog_percent_check( supermob, ch, obj, NULL, GET_PROG );
release_supermob( );
}
}
/*
* called in damage_obj in act_obj.c
*/
void oprog_damage_trigger( CHAR_DATA * ch, OBJ_DATA * obj )
{
if( HAS_PROG( obj->pIndexData, DAMAGE_PROG ) )
{
set_supermob( obj );
oprog_percent_check( supermob, ch, obj, NULL, DAMAGE_PROG );
release_supermob( );
}
}
/*
* called in do_repair in shops.c
*/
void oprog_repair_trigger( CHAR_DATA * ch, OBJ_DATA * obj )
{
if( HAS_PROG( obj->pIndexData, REPAIR_PROG ) )
{
set_supermob( obj );
oprog_percent_check( supermob, ch, obj, NULL, REPAIR_PROG );
release_supermob( );
}
}
/*
* call twice in do_drop, right after the act( AT_ACTION,...)
* do a if(!ch) return right after
*/
void oprog_drop_trigger( CHAR_DATA * ch, OBJ_DATA * obj )
{
if( HAS_PROG( obj->pIndexData, DROP_PROG ) )
{
set_supermob( obj );
oprog_percent_check( supermob, ch, obj, NULL, DROP_PROG );
release_supermob( );
}
}
/*
* call towards end of do_examine, right before check_for_trap
*/
void oprog_examine_trigger( CHAR_DATA * ch, OBJ_DATA * obj )
{
if( HAS_PROG( obj->pIndexData, EXA_PROG ) )
{
set_supermob( obj );
oprog_percent_check( supermob, ch, obj, NULL, EXA_PROG );
release_supermob( );
}
}
/*
* call in fight.c, group_gain, after (?) the obj_to_room
*/
void oprog_zap_trigger( CHAR_DATA * ch, OBJ_DATA * obj )
{
if( HAS_PROG( obj->pIndexData, ZAP_PROG ) )
{
set_supermob( obj );
oprog_percent_check( supermob, ch, obj, NULL, ZAP_PROG );
release_supermob( );
}
}
/*
* call in levers.c, towards top of do_push_or_pull
* see note there
*/
void oprog_pull_trigger( CHAR_DATA * ch, OBJ_DATA * obj )
{
if( HAS_PROG( obj->pIndexData, PULL_PROG ) )
{
set_supermob( obj );
oprog_percent_check( supermob, ch, obj, NULL, PULL_PROG );
release_supermob( );
}
}
/*
* call in levers.c, towards top of do_push_or_pull
* see note there
*/
void oprog_push_trigger( CHAR_DATA * ch, OBJ_DATA * obj )
{
if( HAS_PROG( obj->pIndexData, PUSH_PROG ) )
{
set_supermob( obj );
oprog_percent_check( supermob, ch, obj, NULL, PUSH_PROG );
release_supermob( );
}
}
void obj_act_add( OBJ_DATA * obj );
void oprog_act_trigger( char *buf, OBJ_DATA * mobj, CHAR_DATA * ch, OBJ_DATA * obj, void *vo )
{
if( HAS_PROG( mobj->pIndexData, ACT_PROG ) )
{
MPROG_ACT_LIST *tmp_act, *tmp_mal;
CREATE( tmp_act, MPROG_ACT_LIST, 1 );
/*
* Losing the head of the list -Druid
*/
if( mobj->mpactnum > 0 )
{
tmp_mal = mobj->mpact;
while( tmp_mal->next != NULL )
tmp_mal = tmp_mal->next;
/*
* Put at the end
*/
tmp_mal->next = tmp_act;
}
else
mobj->mpact = tmp_act;
tmp_act->next = NULL;
tmp_act->buf = str_dup( buf );
tmp_act->ch = ch;
tmp_act->obj = obj;
tmp_act->vo = vo;
mobj->mpactnum++;
obj_act_add( mobj );
}
}
void oprog_wordlist_check( char *arg, CHAR_DATA * mob, CHAR_DATA * actor,
OBJ_DATA * obj, void *vo, int type, OBJ_DATA * iobj )
{
char temp1[MAX_STRING_LENGTH];
char temp2[MAX_INPUT_LENGTH];
char word[MAX_INPUT_LENGTH];
MPROG_DATA *mprg;
char *list;
char *start;
char *dupl;
char *end;
int i;
for( mprg = iobj->pIndexData->mudprogs; mprg; mprg = mprg->next )
if( mprg->type == type )
{
strcpy( temp1, mprg->arglist );
list = temp1;
for( i = 0; i < strlen( list ); i++ )
list[i] = LOWER( list[i] );
strcpy( temp2, arg );
dupl = temp2;
for( i = 0; i < strlen( dupl ); i++ )
dupl[i] = LOWER( dupl[i] );
if( ( list[0] == 'p' ) && ( list[1] == ' ' ) )
{
list += 2;
while( ( start = strstr( dupl, list ) ) )
if( ( start == dupl || *( start - 1 ) == ' ' )
&& ( *( end = start + strlen( list ) ) == ' ' || *end == '\n' || *end == '\r' || *end == '\0' ) )
{
set_supermob( iobj );
mprog_driver( mprg->comlist, mob, actor, obj, vo, FALSE );
release_supermob( );
break;
}
else
dupl = start + 1;
}
else
{
list = one_argument( list, word );
for( ; word[0] != '\0'; list = one_argument( list, word ) )
while( ( start = strstr( dupl, word ) ) )
if( ( start == dupl || *( start - 1 ) == ' ' )
&& ( *( end = start + strlen( word ) ) == ' ' || *end == '\n' || *end == '\r' || *end == '\0' ) )
{
set_supermob( iobj );
mprog_driver( mprg->comlist, mob, actor, obj, vo, FALSE );
release_supermob( );
break;
}
else
dupl = start + 1;
}
}
return;
}
/*
* room_prog support starts here
*
*
*/
void rset_supermob( ROOM_INDEX_DATA * room )
{
char buf[200];
if( room )
{
STRFREE( supermob->short_descr );
supermob->short_descr = QUICKLINK( room->name );
STRFREE( supermob->name );
supermob->name = QUICKLINK( room->name );
supermob->mpscriptpos = room->mpscriptpos;
/*
* Added by Jenny to allow bug messages to show the vnum
* of the room, and not just supermob's vnum
*/
sprintf( buf, "Room #%d", room->vnum );
STRFREE( supermob->description );
supermob->description = STRALLOC( buf );
char_from_room( supermob );
char_to_room( supermob, room );
}
}
void rprog_percent_check( CHAR_DATA * mob, CHAR_DATA * actor, OBJ_DATA * obj, void *vo, int type )
{
MPROG_DATA *mprg;
if( !mob->in_room )
return;
for( mprg = mob->in_room->mudprogs; mprg; mprg = mprg->next )
if( mprg->type == type && number_percent( ) <= atoi( mprg->arglist ) )
{
mprog_driver( mprg->comlist, mob, actor, obj, vo, FALSE );
if( type != ENTER_PROG )
break;
}
}
/*
* Triggers follow
*/
/*
* Hold on this
* Unhold. -- Alty
*/
void room_act_add( ROOM_INDEX_DATA * room );
void rprog_act_trigger( char *buf, ROOM_INDEX_DATA * room, CHAR_DATA * ch, OBJ_DATA * obj, void *vo )
{
if( HAS_PROG( room, ACT_PROG ) )
{
MPROG_ACT_LIST *tmp_act, *tmp_mal;
CREATE( tmp_act, MPROG_ACT_LIST, 1 );
/*
* Losing the head of the list -Druid
*/
if( room->mpactnum > 0 )
{
tmp_mal = room->mpact;
while( tmp_mal->next != NULL )
tmp_mal = tmp_mal->next;
/*
* Put at the end
*/
tmp_mal->next = tmp_act;
}
else
room->mpact = tmp_act;
tmp_act->next = NULL;
tmp_act->buf = str_dup( buf );
tmp_act->ch = ch;
tmp_act->obj = obj;
tmp_act->vo = vo;
room->mpactnum++;
room_act_add( room );
}
}
/*
*
*/
void rprog_leave_trigger( CHAR_DATA * ch )
{
if( HAS_PROG( ch->in_room, LEAVE_PROG ) )
{
rset_supermob( ch->in_room );
rprog_percent_check( supermob, ch, NULL, NULL, LEAVE_PROG );
release_supermob( );
}
}
void rprog_enter_trigger( CHAR_DATA * ch )
{
if( HAS_PROG( ch->in_room, ENTER_PROG ) )
{
rset_supermob( ch->in_room );
rprog_percent_check( supermob, ch, NULL, NULL, ENTER_PROG );
release_supermob( );
}
}
void rprog_sleep_trigger( CHAR_DATA * ch )
{
if( HAS_PROG( ch->in_room, SLEEP_PROG ) )
{
rset_supermob( ch->in_room );
rprog_percent_check( supermob, ch, NULL, NULL, SLEEP_PROG );
release_supermob( );
}
}
void rprog_rest_trigger( CHAR_DATA * ch )
{
if( HAS_PROG( ch->in_room, REST_PROG ) )
{
rset_supermob( ch->in_room );
rprog_percent_check( supermob, ch, NULL, NULL, REST_PROG );
release_supermob( );
}
}
void rprog_rfight_trigger( CHAR_DATA * ch )
{
if( HAS_PROG( ch->in_room, RFIGHT_PROG ) )
{
rset_supermob( ch->in_room );
rprog_percent_check( supermob, ch, NULL, NULL, RFIGHT_PROG );
release_supermob( );
}
}
void rprog_death_trigger( CHAR_DATA * killer, CHAR_DATA * ch )
{
if( HAS_PROG( ch->in_room, RDEATH_PROG ) )
{
rset_supermob( ch->in_room );
rprog_percent_check( supermob, ch, NULL, NULL, RDEATH_PROG );
release_supermob( );
}
}
void rprog_speech_trigger( char *txt, CHAR_DATA * ch )
{
if( HAS_PROG( ch->in_room, SPEECH_PROG ) )
{
/*
* supermob is set and released in rprog_wordlist_check
*/
rprog_wordlist_check( txt, supermob, ch, NULL, NULL, SPEECH_PROG, ch->in_room );
}
}
void rprog_random_trigger( CHAR_DATA * ch )
{
if( HAS_PROG( ch->in_room, RAND_PROG ) )
{
rset_supermob( ch->in_room );
rprog_percent_check( supermob, ch, NULL, NULL, RAND_PROG );
release_supermob( );
}
}
void rprog_wordlist_check( char *arg, CHAR_DATA * mob, CHAR_DATA * actor,
OBJ_DATA * obj, void *vo, int type, ROOM_INDEX_DATA * room )
{
char temp1[MAX_STRING_LENGTH];
char temp2[MAX_INPUT_LENGTH];
char word[MAX_INPUT_LENGTH];
MPROG_DATA *mprg;
char *list;
char *start;
char *dupl;
char *end;
int i;
if( actor && !char_died( actor ) && actor->in_room )
room = actor->in_room;
for( mprg = room->mudprogs; mprg; mprg = mprg->next )
if( mprg->type == type )
{
strcpy( temp1, mprg->arglist );
list = temp1;
for( i = 0; i < strlen( list ); i++ )
list[i] = LOWER( list[i] );
strcpy( temp2, arg );
dupl = temp2;
for( i = 0; i < strlen( dupl ); i++ )
dupl[i] = LOWER( dupl[i] );
if( ( list[0] == 'p' ) && ( list[1] == ' ' ) )
{
list += 2;
while( ( start = strstr( dupl, list ) ) )
if( ( start == dupl || *( start - 1 ) == ' ' )
&& ( *( end = start + strlen( list ) ) == ' ' || *end == '\n' || *end == '\r' || *end == '\0' ) )
{
rset_supermob( room );
mprog_driver( mprg->comlist, mob, actor, obj, vo, FALSE );
release_supermob( );
break;
}
else
dupl = start + 1;
}
else
{
list = one_argument( list, word );
for( ; word[0] != '\0'; list = one_argument( list, word ) )
while( ( start = strstr( dupl, word ) ) )
if( ( start == dupl || *( start - 1 ) == ' ' )
&& ( *( end = start + strlen( word ) ) == ' ' || *end == '\n' || *end == '\r' || *end == '\0' ) )
{
rset_supermob( room );
mprog_driver( mprg->comlist, mob, actor, obj, vo, FALSE );
release_supermob( );
break;
}
else
dupl = start + 1;
}
}
return;
}
void rprog_time_check( CHAR_DATA * mob, CHAR_DATA * actor, OBJ_DATA * obj, void *vo, int type )
{
ROOM_INDEX_DATA *room = ( ROOM_INDEX_DATA * ) vo;
MPROG_DATA *mprg;
bool trigger_time;
for( mprg = room->mudprogs; mprg; mprg = mprg->next )
{
trigger_time = ( time_info.hour == atoi( mprg->arglist ) );
if( !trigger_time )
{
if( mprg->triggered )
mprg->triggered = FALSE;
continue;
}
if( mprg->type == type && ( ( !mprg->triggered ) || ( mprg->type == HOUR_PROG ) ) )
{
mprg->triggered = TRUE;
mprog_driver( mprg->comlist, mob, actor, obj, vo, FALSE );
}
}
return;
}
void rprog_time_trigger( CHAR_DATA * ch )
{
if( HAS_PROG( ch->in_room, TIME_PROG ) )
{
rset_supermob( ch->in_room );
rprog_time_check( supermob, NULL, NULL, ch->in_room, TIME_PROG );
release_supermob( );
}
}
void rprog_hour_trigger( CHAR_DATA * ch )
{
if( HAS_PROG( ch->in_room, HOUR_PROG ) )
{
rset_supermob( ch->in_room );
rprog_time_check( supermob, NULL, NULL, ch->in_room, HOUR_PROG );
release_supermob( );
}
}
/* Written by Jenny, Nov 29/95 */
void progbug( char *str, CHAR_DATA * mob )
{
char buf[MAX_STRING_LENGTH];
int vnum = mob->pIndexData ? mob->pIndexData->vnum : 0;
/*
* Check if we're dealing with supermob, which means the bug occurred
* in a room or obj prog.
*/
if( vnum == 3 )
{
/*
* It's supermob. In set_supermob and rset_supermob, the description
* was set to indicate the object or room, so we just need to show
* the description in the bug message.
*/
sprintf( buf, "%s, %s.", str, mob->description == NULL ? "(unknown)" : mob->description );
}
else
{
sprintf( buf, "%s, Mob #%d.", str, vnum );
}
bug( buf, 0 );
return;
}
/* Room act prog updates. Use a separate list cuz we dont really wanna go
thru 5-10000 rooms every pulse.. can we say lag? -- Alty */
void room_act_add( ROOM_INDEX_DATA * room )
{
struct act_prog_data *runner, *tmp_ral;
for( runner = room_act_list; runner; runner = runner->next )
if( runner->vo == room )
return;
CREATE( runner, struct act_prog_data, 1 );
runner->vo = room;
runner->next = NULL;
/*
* The head of the list is being changed in
* room_act_update, So append to the end of the list
* instead. -Druid
*/
if( room_act_list )
{
tmp_ral = room_act_list;
while( tmp_ral->next != NULL )
tmp_ral = tmp_ral->next;
/*
* put at the end
*/
tmp_ral->next = runner;
}
else
room_act_list = runner;
}
void room_act_update( void )
{
struct act_prog_data *runner;
MPROG_ACT_LIST *mpact;
while( ( runner = room_act_list ) != NULL )
{
ROOM_INDEX_DATA *room = runner->vo;
while( ( mpact = room->mpact ) != NULL )
{
if( mpact->ch->in_room == room )
rprog_wordlist_check( mpact->buf, supermob, mpact->ch, mpact->obj, mpact->vo, ACT_PROG, room );
room->mpact = mpact->next;
DISPOSE( mpact->buf );
DISPOSE( mpact );
}
room->mpact = NULL;
room->mpactnum = 0;
room_act_list = runner->next;
DISPOSE( runner );
}
return;
}
void obj_act_add( OBJ_DATA * obj )
{
struct act_prog_data *runner, *tmp_oal;
for( runner = obj_act_list; runner; runner = runner->next )
if( runner->vo == obj )
return;
CREATE( runner, struct act_prog_data, 1 );
runner->vo = obj;
runner->next = NULL;
/*
* The head of the list is being changed in
* obj_act_update, So append to the end of the list
* instead. -Druid
*/
if( obj_act_list )
{
tmp_oal = obj_act_list;
while( tmp_oal->next != NULL )
tmp_oal = tmp_oal->next;
/*
* put at the end
*/
tmp_oal->next = runner;
}
else
obj_act_list = runner;
}
void obj_act_update( void )
{
struct act_prog_data *runner;
MPROG_ACT_LIST *mpact;
while( ( runner = obj_act_list ) != NULL )
{
OBJ_DATA *obj = runner->vo;
while( ( mpact = obj->mpact ) != NULL )
{
oprog_wordlist_check( mpact->buf, supermob, mpact->ch, mpact->obj, mpact->vo, ACT_PROG, obj );
obj->mpact = mpact->next;
DISPOSE( mpact->buf );
DISPOSE( mpact );
}
obj->mpact = NULL;
obj->mpactnum = 0;
obj_act_list = runner->next;
DISPOSE( runner );
}
return;
}
void do_mpquestcomplete( CHAR_DATA * ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
if( !IS_NPC( ch ) || IS_AFFECTED( ch, AFF_CHARM ) )
{
send_to_char( "Huh?\n\r", ch );
return;
}
argument = one_argument( argument, arg );
if( arg[0] == '\0' )
{
progbug( "Mpquestcomplete - No argument", ch );
return;
}
if( !( victim = get_char_room( ch, arg ) ) )
{
progbug( "Mpquestcomplete - victim does not exist", ch );
return;
}
if( IS_NPC( victim ) )
{
send_to_char( "Mobs can't have quests!\n\r", ch );
return;
}
if( argument[0] == '\0' )
{
progbug( "Mpquestcomplete - no quest to complete", ch );
return;
}
if( argument[strlen( argument ) - 1] == '\0' )
{
argument[strlen( argument ) - 1] = '\0';
}
MarkQuestComplete( argument, victim );
}