/***************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************/
/***************************************************************************
* The MOBprograms have been contributed by N'Atas-ha. Any support for *
* these routines should not be expected from Merc Industries. However, *
* under no circumstances should the blame for bugs, etc be placed on *
* Merc Industries. They are not guaranteed to work on all systems due *
* to their frequent use of strxxx functions. They are also not the most *
* efficient way to perform their tasks, but hopefully should be in the *
* easiest possible way to install and begin using. Documentation for *
* such installation can be found in INSTALL. Enjoy... N'Atas-Ha *
***************************************************************************/
/***************************************************************************
* Heavy modifications were made to Mobprogs (now MudProgs) by Thanatos, *
* Zak and Zane *
***************************************************************************/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "merc.h"
#include "interp.h"
/*
* Local function prototypes
*/
char * mprog_next_command args( ( char* clist ) );
bool mprog_seval args( ( char* lhs, char* opr, char* rhs ) );
bool mprog_veval args( ( int lhs, char* opr, int rhs ) );
long mprog_do_ifchck args( ( char* ifchck, CHAR_DATA* mob,
CHAR_DATA* actor, OBJ_DATA* obj,
void* vo, CHAR_DATA* rndm, CHAR_DATA* evil ) );
char * mprog_process_if args( ( char* ifchck, char* com_list,
CHAR_DATA* mob, CHAR_DATA* actor,
OBJ_DATA* obj, void* vo,
CHAR_DATA* rndm, CHAR_DATA *evil ) );
void mprog_translate args( ( char ch, char* t, CHAR_DATA* mob,
CHAR_DATA* actor, OBJ_DATA* obj,
void* vo, CHAR_DATA* rndm, CHAR_DATA *evil ) );
void mprog_process_cmnd args( ( char* cmnd, CHAR_DATA* mob,
CHAR_DATA* actor, OBJ_DATA* obj,
void* vo, CHAR_DATA* rndm, CHAR_DATA *evil ) );
void mprog_driver args( ( char* com_list, CHAR_DATA* mob,
CHAR_DATA* actor, OBJ_DATA* obj,
void* vo ) );
void set_supermob args( ( void *source, int prog_type ) );
void release_supermob args( ( void ) );
void room_act_add args( ( ROOM_INDEX_DATA *room ) );
/*
* Structure needed to efficiently handle room and object act
* triggers.
*/
struct act_prog_data
{
struct act_prog_data *next;
void *vo;
};
CHAR_DATA *supermob;
struct act_prog_data *room_act_list;
struct act_prog_data *obj_act_list;
/***************************************************************************
* 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
/* 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 )
{
char *pointer = clist;
if ( !pointer )
return NULL;
while ( *pointer != '\n' && *pointer != '\r' && *pointer != '\0' )
pointer++;
/* Strip \n\r and/or \r\n */
if ( *pointer == '\n' )
*pointer++ = '\0';
else if ( *pointer == '\r' )
*pointer++ = '\0';
if ( *pointer == '\n' )
*pointer++ = '\0';
else 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 )
{
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 ) );
bug ( "Improper MudProg operator\n\r", 0 );
return 0;
}
bool mprog_veval( int lhs, char *opr, int 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 );
if ( !str_cmp( opr, "|" ) )
return ( lhs | rhs );
bug ( "Improper MudProg operator\n\r", 0 );
return 0;
}
/* 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: ifchck ( 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 -1 otherwise return boolean 1,0
*/
long mprog_do_ifchck( char *ifchck, CHAR_DATA *mob, CHAR_DATA *actor,
OBJ_DATA *obj, void *vo, CHAR_DATA *rndm, CHAR_DATA *evil)
{
char buf[ MAX_INPUT_LENGTH ];
char arg[ MAX_INPUT_LENGTH ];
char opr[ MAX_INPUT_LENGTH ];
char val[ MAX_INPUT_LENGTH ];
CHAR_DATA *pMob;
CHAR_DATA *vict = (CHAR_DATA *) vo;
OBJ_DATA *v_obj = (OBJ_DATA *) vo;
char *bufpt = buf;
char *argpt = arg;
char *oprpt = opr;
char *valpt = val;
char *point = ifchck;
int lhsvl;
int rhsvl;
if ( *point == '\0' )
{
bug ( "Mob: %d null ifchck", mob->pIndexData->vnum );
return -1;
}
/* skip leading spaces */
while ( *point == ' ' )
point++;
/* get whatever comes before the left paren.. ignore spaces */
while ( *point != '(' )
if ( *point == '\0' )
{
bug ( "Mob: %d ifchck syntax error", mob->pIndexData->vnum );
return -1;
}
else
if ( *point == ' ' )
point++;
else
*bufpt++ = *point++;
*bufpt = '\0';
point++;
/* get whatever is in between the parens.. ignore spaces */
while ( *point != ')' )
if ( *point == '\0' )
{
bug ( "Mob: %d ifchck syntax error", mob->pIndexData->vnum );
return -1;
}
else
if ( *point == ' ' )
point++;
else
*argpt++ = *point++;
*argpt = '\0';
point++;
/* check to see if there is an operator */
while ( *point == ' ' )
point++;
if ( *point == '\0' )
{
*opr = '\0';
*val = '\0';
}
else /* there should be an operator and value, so get them */
{
while ( ( *point != ' ' ) && ( !isalnum( *point ) ) )
if ( *point == '\0' )
{
bug ( "Mob: %d ifchck operator without value",
mob->pIndexData->vnum );
return -1;
}
else
*oprpt++ = *point++;
*oprpt = '\0';
/* finished with operator, skip spaces and then get the value */
while ( *point == ' ' )
point++;
for( ; ; )
{
if ( ( *point != ' ' ) && ( *point == '\0' ) )
break;
else
*valpt++ = *point++;
}
*valpt = '\0';
}
bufpt = buf;
argpt = arg;
oprpt = opr;
valpt = val;
/* Ok... now buf contains the ifchck, arg contains the inside of the
* parentheses, opr contains an operator if one is present, and val
* has the value if an operator was present.
* So.. basically use if statements and run over all known ifchecks
* Once inside, use the argument and expand the lhs. Then if need be
* send the lhs,opr,rhs off to be evaluated.
*/
if ( !str_cmp( buf, "memory" ) )
{ /* if memory() returns TRUE if anything is in memory */
/* if memory() == $* returns TRUE if memory ==,!=,/,!/ $* */
if ( mob->memory == NULL ) return FALSE;
else if (get_char_world(mob,mob->memory->name) == NULL) return FALSE;
if (opr[0]=='\0') return TRUE;
if (val[0]=='$') switch (val[1])
{
case 'i': return FALSE; /* can't remember myself */
case 'n': if (actor)
return mprog_seval(actor->name,opr,mob->memory->name);
else return -1;
case 't': if (vict)
return mprog_seval(vict->name,opr,mob->memory->name);
else return -1;
case 'r': if (rndm)
return mprog_seval(rndm->name,opr,mob->memory->name);
else return -1;
case 'x': if (evil)
return mprog_seval(evil->name,opr,mob->memory->name);
else return -1;
default : bug("Mob: %d bad val for 'if memory'",mob->pIndexData->vnum);
return -1;
}
return mprog_seval(val,opr,mob->memory->name);
}
if ( !str_cmp( buf, "rand" ) )
{
return ( number_percent() <= atoi(arg) );
}
if ( !str_cmp(buf, "getrand" ) )
{
lhsvl = number_range(1, atoi(arg));
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
if ( !str_cmp(buf, "fightinroom" ) )
{
for (pMob = mob->in_room->people; pMob && !pMob->fighting; pMob = pMob->next_in_room)
;
if ( pMob )
lhsvl = 1;
else
lhsvl = 0;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
if ( !str_cmp(buf, "hour" ) )
{
lhsvl = time_info.hour;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
if ( !str_cmp( buf, "ispc" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': return 0;
case 'n': if ( actor )
return ( !IS_NPC( actor ) );
else return -1;
case 't': if ( vict )
return ( !IS_NPC( vict ) );
else return -1;
case 'r': if ( rndm )
return ( !IS_NPC( rndm ) );
else return -1;
case 'x': if ( evil )
return ( !IS_NPC( evil ) );
else return -1;
default:
bug ( "Mob: %d bad argument to 'ispc'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "isnpc" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': return 1;
case 'n': if ( actor )
return IS_NPC( actor );
else return -1;
case 't': if ( vict )
return IS_NPC( vict );
else return -1;
case 'r': if ( rndm )
return IS_NPC( rndm );
else return -1;
case 'x': if ( evil )
return IS_NPC( evil );
else return -1;
default:
bug ("Mob: %d bad argument to 'isnpc'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "isgood" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': return IS_GOOD( mob );
case 'n': if ( actor )
return IS_GOOD( actor );
else return -1;
case 't': if ( vict )
return IS_GOOD( vict );
else return -1;
case 'r': if ( rndm )
return IS_GOOD( rndm );
else return -1;
case 'x': if ( evil )
return IS_GOOD( evil );
else return -1;
default:
bug ( "Mob: %d bad argument to 'isgood'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "isfight" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': return ( mob->fighting ) ? 1 : 0;
case 'n': if ( actor )
return ( actor->fighting ) ? 1 : 0;
else return -1;
case 't': if ( vict )
return ( vict->fighting ) ? 1 : 0;
else return -1;
case 'r': if ( rndm )
return ( rndm->fighting ) ? 1 : 0;
else return -1;
case 'x': if ( evil )
return ( evil->fighting ) ? 1 : 0;
else return -1;
default:
bug ( "Mob: %d bad argument to 'isfight'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "isimmort" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': return ( get_trust( mob ) > LEVEL_IMMORTAL );
case 'n': if ( actor )
return ( get_trust( actor ) > LEVEL_IMMORTAL );
else return -1;
case 't': if ( vict )
return ( get_trust( vict ) > LEVEL_IMMORTAL );
else return -1;
case 'r': if ( rndm )
return ( get_trust( rndm ) > LEVEL_IMMORTAL );
else return -1;
case 'x': if ( evil )
return ( get_trust( evil ) > LEVEL_IMMORTAL );
else return -1;
default:
bug ( "Mob: %d bad argument to 'isimmort'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "ischarmed" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': return IS_SET( mob->affected_by , AFF_CHARM );
case 'n': if ( actor )
return IS_AFFECTED( actor, AFF_CHARM );
else return -1;
case 't': if ( vict )
return IS_AFFECTED( vict, AFF_CHARM );
else return -1;
case 'r': if ( rndm )
return IS_AFFECTED( rndm, AFF_CHARM );
else return -1;
case 'x': if ( evil )
return IS_AFFECTED( evil, AFF_CHARM );
else return -1;
default:
bug ( "Mob: %d bad argument to 'ischarmed'",
mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "isfollow" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': return ( mob->master != NULL
&& mob->master->in_room == mob->in_room );
case 'n': if ( actor )
return ( actor->master != NULL
&& actor->master->in_room == actor->in_room );
else return -1;
case 't': if ( vict )
return ( vict->master != NULL
&& vict->master->in_room == vict->in_room );
else return -1;
case 'r': if ( rndm )
return ( rndm->master != NULL
&& rndm->master->in_room == rndm->in_room );
else return -1;
case 'x': if ( evil )
return ( evil->master != NULL
&& evil->master->in_room == evil->in_room );
else return -1;
default:
bug ( "Mob: %d bad argument to 'isfollow'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "isaffected" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': return ( mob->affected_by & atoi( arg ) );
case 'n': if ( actor )
return ( actor->affected_by & atoi( arg ) );
else return -1;
case 't': if ( vict )
return ( vict->affected_by & atoi( arg ) );
else return -1;
case 'r': if ( rndm )
return ( rndm->affected_by & atoi( arg ) );
else return -1;
case 'x': if ( evil )
return ( evil->affected_by & atoi( arg ) );
else return -1;
default:
bug ( "Mob: %d bad argument to 'isaffected'",
mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "hitprcnt" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': lhsvl = mob->hit / mob->max_hit;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
case 'n': if ( actor )
{
lhsvl = actor->hit / actor->max_hit;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 't': if ( vict )
{
lhsvl = vict->hit / vict->max_hit;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'r': if ( rndm )
{
lhsvl = rndm->hit / rndm->max_hit;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'x': if ( evil )
{
lhsvl = evil->hit / evil->max_hit;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
default:
bug ( "Mob: %d bad argument to 'hitprcnt'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "inroom" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': lhsvl = mob->in_room->vnum;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
case 'n': if ( actor )
{
lhsvl = actor->in_room->vnum;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 't': if ( vict )
{
lhsvl = vict->in_room->vnum;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'r': if ( rndm )
{
lhsvl = rndm->in_room->vnum;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'x': if ( evil )
{
lhsvl = evil->in_room->vnum;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
default:
bug ( "Mob: %d bad argument to 'inroom'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "crimethief" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': lhsvl = IS_SET(mob->act, PLR_THIEF);
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
case 'n': if ( actor )
{
lhsvl = IS_SET(actor->act, PLR_THIEF);
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 't': if ( vict )
{
lhsvl = IS_SET(vict->act, PLR_THIEF);
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'r': if ( rndm )
{
lhsvl = IS_SET(rndm->act, PLR_THIEF);
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'x': if ( evil )
{
lhsvl = IS_SET(evil->act, PLR_THIEF);
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
default:
bug ( "Mob: %d bad argument to 'inroom'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "alignment" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': lhsvl = mob->alignment;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
case 'n': if ( actor )
{
lhsvl = actor->alignment;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 't': if ( vict )
{
lhsvl = vict->alignment;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'r': if ( rndm )
{
lhsvl = rndm->alignment;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'x': if ( evil )
{
lhsvl = evil->alignment;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
default:
bug ( "Mob: %d bad argument to 'alignment'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "sex" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': lhsvl = mob->sex;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
case 'n': if ( actor )
{
lhsvl = actor->sex;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 't': if ( vict )
{
lhsvl = vict->sex;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'r': if ( rndm )
{
lhsvl = rndm->sex;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'x': if ( evil )
{
lhsvl = evil->sex;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
default:
bug ( "Mob: %d bad argument to 'sex'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "position" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': lhsvl = mob->position;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
case 'n': if ( actor )
{
lhsvl = actor->position;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 't': if ( vict )
{
lhsvl = vict->position;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'r': if ( rndm )
{
lhsvl = rndm->position;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'x': if ( evil )
{
lhsvl = evil->position;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
default:
bug ( "Mob: %d bad argument to 'position'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "level" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': lhsvl = get_trust( mob );
if ( *opr == '\0' )
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
case 'n': if ( actor )
{
lhsvl = get_trust( actor );
if ( *opr == '\0' )
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 't': if ( vict )
{
lhsvl = get_trust( vict );
if ( *opr == '\0' )
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'r': if ( rndm )
{
lhsvl = get_trust( rndm );
if ( *opr == '\0' )
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'x': if ( evil )
{
lhsvl = get_trust( evil );
if ( *opr == '\0' )
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
default:
bug ( "Mob: %d bad argument to 'level'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "immune" ) )
{
if ( !obj )
return FALSE;
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': lhsvl = check_immune( mob, attack_table[obj->value[3]].damage );
if ( *opr == '\0' )
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
case 'n': if ( actor )
{
lhsvl = check_immune( actor, attack_table[obj->value[3]].damage );
if ( *opr == '\0' )
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'r': if ( rndm )
{
lhsvl = check_immune( rndm, attack_table[obj->value[3]].damage );
if ( *opr == '\0' )
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'x': if ( evil )
{
lhsvl = check_immune( evil, attack_table[obj->value[3]].damage );
if ( *opr == '\0' )
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 't': if ( vict )
{
lhsvl = check_immune( vict, attack_table[obj->value[3]].damage );
if ( *opr == '\0' )
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
default:
bug ( "Mob: %d bad argument to 'immune'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "class" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': lhsvl = mob->Class;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
case 'n': if ( actor )
{
lhsvl = actor->Class;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 't': if ( vict )
{
lhsvl = vict->Class;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'r': if ( rndm )
{
lhsvl = rndm->Class;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'x': if ( evil )
{
lhsvl = evil->Class;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
default:
bug ( "Mob: %d bad argument to 'class'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "goldamt" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': lhsvl = mob->gold;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
case 'n': if ( actor )
{
lhsvl = actor->gold;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 't': if ( vict )
{
lhsvl = vict->gold;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'r': if ( rndm )
{
lhsvl = rndm->gold;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'x': if ( evil )
{
lhsvl = evil->gold;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
default:
bug ( "Mob: %d bad argument to 'goldamt'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "objtype" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'o': if ( obj )
{
lhsvl = obj->item_type;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'p': if ( v_obj )
{
lhsvl = v_obj->item_type;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
default:
bug ( "Mob: %d bad argument to 'objtype'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "objval0" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'o': if ( obj )
{
lhsvl = obj->value[0];
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'p': if ( v_obj )
{
lhsvl = v_obj->value[0];
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
default:
bug ( "Mob: %d bad argument to 'objval0'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "objval1" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'o': if ( obj )
{
lhsvl = obj->value[1];
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'p': if ( v_obj )
{
lhsvl = v_obj->value[1];
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
default:
bug ( "Mob: %d bad argument to 'objval1'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "objval2" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'o': if ( obj )
{
lhsvl = obj->value[2];
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'p': if ( v_obj )
{
lhsvl = v_obj->value[2];
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
default:
bug ( "Mob: %d bad argument to 'objval2'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "objval3" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'o': if ( obj )
{
lhsvl = obj->value[3];
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'p': if ( v_obj )
{
lhsvl = v_obj->value[3];
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
default:
bug ( "Mob: %d bad argument to 'objval3'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "number" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': lhsvl = mob->gold;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
case 'n': if ( actor )
{
if IS_NPC( actor )
{
lhsvl = actor->pIndexData->vnum;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
}
else
return -1;
case 't': if ( vict )
{
if IS_NPC( actor )
{
lhsvl = vict->pIndexData->vnum;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
}
else
return -1;
case 'r': if ( rndm )
{
if IS_NPC( actor )
{
lhsvl = rndm->pIndexData->vnum;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
}
else return -1;
case 'x': if ( evil )
{
if IS_NPC( actor )
{
lhsvl = evil->pIndexData->vnum;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
}
else return -1;
case 'o': if ( obj )
{
lhsvl = obj->pIndexData->vnum;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
case 'p': if ( v_obj )
{
lhsvl = v_obj->pIndexData->vnum;
if (*opr == '\0')
{
return lhsvl;
}
else
{
if ( strstr(val, "(") )
{
rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
}
else
{
rhsvl = atoi( val );
}
return mprog_veval( lhsvl, opr, rhsvl );
}
}
else
return -1;
default:
bug ( "Mob: %d bad argument to 'number'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "name" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': return mprog_seval( mob->name, opr, val );
case 'n': if ( actor )
return mprog_seval( actor->name, opr, val );
else
return -1;
case 't': if ( vict )
return mprog_seval( vict->name, opr, val );
else
return -1;
case 'r': if ( rndm )
return mprog_seval( rndm->name, opr, val );
else
return -1;
case 'x': if ( evil )
return mprog_seval( evil->name, opr, val );
else
return -1;
case 'o': if ( obj )
return mprog_seval( obj->name, opr, val );
else
return -1;
case 'p': if ( v_obj )
return mprog_seval( v_obj->name, opr, val );
else
return -1;
default:
bug ( "Mob: %d bad argument to 'name'", mob->pIndexData->vnum );
return -1;
}
}
/* Ok... all the ifchcks are done, so if we didnt find ours then something
* odd happened. So report the bug and abort the MudProg (return error)
*/
bug ( "Mob: %d unknown ifchck = %s", mob->pIndexData->vnum, buf );
return -1;
}
/* Quite a long and arduous function, this guy handles the control
* flow part of MudProgs. Basicially once the driver sees an
* 'if' attention shifts to here. While many syntax errors are
* caught, some will still get through due to the handling of break
* and errors in the same fashion. The desire to break out of the
* recursion without catastrophe in the event of a mis-parse was
* believed to be high. Thus, if an error is found, it is bugged and
* the parser acts as though a break were issued and just bails out
* at that point. I havent tested all the possibilites, so I'm speaking
* in theory, but it is 'guaranteed' to work on syntactically correct
* MudProgs, so if the mud crashes here, check the mob carefully!
*/
char *mprog_process_if( char *ifchck, char *com_list, CHAR_DATA *mob,
CHAR_DATA *actor, OBJ_DATA *obj, void *vo,
CHAR_DATA *rndm, CHAR_DATA *evil )
{
char null[ 1 ];
char buf[ MAX_INPUT_LENGTH ];
char *morebuf = '\0';
char *cmnd = '\0';
bool loopdone = FALSE;
bool flag = FALSE;
long legal;
*null = '\0';
/* check for trueness of the ifcheck */
if ( ( legal = mprog_do_ifchck( ifchck, mob, actor, obj, vo, rndm, evil ) ) )
if ( legal == 1 )
flag = TRUE;
else
return '\0';
while( loopdone == FALSE ) /*scan over any existing or statements */
{
cmnd = com_list;
com_list = mprog_next_command( com_list );
while ( *cmnd == ' ' )
cmnd++;
if ( *cmnd == '\0' )
{
bug ( "Mob: %d no commands after IF/OR/AND", mob->pIndexData->vnum );
return '\0';
}
morebuf = one_argument( cmnd, buf );
if ( !str_cmp( buf, "or" ) )
{
if ( ( legal = mprog_do_ifchck( morebuf,mob,actor,obj,vo,rndm, evil ) ) )
if ( legal == 1 )
flag = TRUE;
else
return '\0';
}
else if ( !str_cmp( buf, "and" ) )
{
if ( ( legal = mprog_do_ifchck( morebuf,mob,actor,obj,vo,rndm, evil ) ) )
if ( legal == 1 )
flag = flag && TRUE;
else
return '\0';
}
else
loopdone = TRUE;
}
if ( flag )
for ( ; ; ) /*ifcheck was true, do commands but ignore else to endif*/
{
if ( !str_cmp( buf, "if" ) )
{
com_list = mprog_process_if(morebuf,com_list,mob,actor,obj,vo,rndm,evil);
while ( *cmnd==' ' )
cmnd++;
if ( *com_list == '\0' )
return '\0';
cmnd = com_list;
com_list = mprog_next_command( com_list );
morebuf = one_argument( cmnd,buf );
continue;
}
if ( !str_cmp( buf, "break" ) )
return '\0';
if ( !str_cmp( buf, "endif" ) )
return com_list;
if ( !str_cmp( buf, "else" ) )
{
while ( str_cmp( buf, "endif" ) )
{
cmnd = com_list;
com_list = mprog_next_command( com_list );
while ( *cmnd == ' ' )
cmnd++;
if ( *cmnd == '\0' )
{
bug ( "Mob: %d missing endif after else",
mob->pIndexData->vnum );
return '\0';
}
morebuf = one_argument( cmnd,buf );
}
return com_list;
}
mprog_process_cmnd( cmnd, mob, actor, obj, vo, rndm, evil );
cmnd = com_list;
com_list = mprog_next_command( com_list );
while ( *cmnd == ' ' )
cmnd++;
if ( *cmnd == '\0' )
{
bug ( "Mob: %d missing else or endif", mob->pIndexData->vnum );
return '\0';
}
morebuf = one_argument( cmnd, buf );
}
else /*false ifcheck, find else and do existing commands or quit at endif*/
{
while ( ( str_cmp( buf, "else" ) ) && ( str_cmp( buf, "endif" ) ) )
{
cmnd = com_list;
com_list = mprog_next_command( com_list );
while ( *cmnd == ' ' )
cmnd++;
if ( *cmnd == '\0' )
{
bug ( "Mob: %d missing an else or endif",
mob->pIndexData->vnum );
return '\0';
}
morebuf = one_argument( cmnd, buf );
}
/* found either an else or an endif.. act accordingly */
if ( !str_cmp( buf, "endif" ) )
return com_list;
cmnd = com_list;
com_list = mprog_next_command( com_list );
while ( *cmnd == ' ' )
cmnd++;
if ( *cmnd == '\0' )
{
bug ( "Mob: %d missing endif", mob->pIndexData->vnum );
return '\0';
}
morebuf = one_argument( cmnd, buf );
for ( ; ; ) /*process the post-else commands until an endif is found.*/
{
if ( !str_cmp( buf, "if" ) )
{
com_list = mprog_process_if( morebuf, com_list, mob, actor,
obj, vo, rndm, evil );
while ( *cmnd == ' ' )
cmnd++;
if ( *com_list == '\0' )
return '\0';
cmnd = com_list;
com_list = mprog_next_command( com_list );
morebuf = one_argument( cmnd,buf );
continue;
}
if ( !str_cmp( buf, "else" ) )
{
bug ( "Mob: %d found else in an else section",
mob->pIndexData->vnum );
return '\0';
}
if ( !str_cmp( buf, "break" ) )
return '\0';
if ( !str_cmp( buf, "endif" ) )
return com_list;
mprog_process_cmnd( cmnd, mob, actor, obj, vo, rndm, evil );
cmnd = com_list;
com_list = mprog_next_command( com_list );
while ( *cmnd == ' ' )
cmnd++;
if ( *cmnd == '\0' )
{
bug ( "Mob:%d missing endif in else section",
mob->pIndexData->vnum );
return '\0';
}
morebuf = one_argument( cmnd, buf );
}
}
}
/* 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.
*/
void mprog_translate( char ch, char *t, CHAR_DATA *mob, CHAR_DATA *actor,
OBJ_DATA *obj, void *vo, CHAR_DATA *rndm, CHAR_DATA *evil )
{
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;
*t = '\0';
switch ( ch ) {
/*
* Mob that has the mob prog
*/
case 'i':
one_argument( mob->name, t );
break;
case 'I':
strcpy( t, mob->short_descr );
break;
/*
* char that triggered the mob prog
*/
case 'n':
if ( actor )
{
if ( can_see( mob,actor ) )
one_argument( actor->name, t );
if ( !IS_NPC( actor ) )
*t = UPPER( *t );
}
else
{
bug( "Mprog_Translate: case 'n', NULL actor" );
strcpy( t, "someone" );
}
break;
case 'N':
if ( actor )
if ( can_see( mob, actor ) )
if ( IS_NPC( actor ) )
strcpy( t, actor->short_descr );
else
{
strcpy( t, actor->name );
strcat( t, " " );
strcat( t, actor->pcdata->title );
}
else
strcpy( t, "someone" );
break;
/*
* used for victim
*/
case 't':
if ( vict )
{
if ( can_see( mob, vict ) )
one_argument( vict->name, t );
if ( !IS_NPC( vict ) )
*t = UPPER( *t );
}
else
{
strcpy( t, "someone" );
}
break;
case 'T':
if ( vict )
if ( can_see( mob, vict ) )
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" );
break;
case 'r':
if ( rndm )
{
if ( can_see( mob, rndm ) )
one_argument( rndm->name, t );
if ( !IS_NPC( rndm ) )
*t = UPPER( *t );
}
else
strcpy( t, "someone" );
break;
case 'R':
if ( rndm )
if ( can_see( mob, rndm ) )
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" );
break;
case 'x':
if ( evil )
{
if ( can_see( mob, evil ) )
one_argument( evil->name, t );
if ( !IS_NPC( evil ) )
*t = UPPER( *t );
}
else
strcpy( t, "someone" );
break;
case 'X':
if ( evil )
if ( can_see( mob, evil ) )
if ( IS_NPC( evil ) )
strcpy(t,evil->short_descr);
else
{
strcpy( t, evil->name );
strcat( t, " " );
strcat( t, evil->pcdata->title );
}
else
strcpy( t, "someone" );
break;
case 'e':
if ( actor )
can_see( mob, actor ) ? strcpy( t, he_she[ actor->sex ] )
: strcpy( t, "someone" );
break;
case 'm':
if ( actor )
can_see( mob, actor ) ? strcpy( t, him_her[ actor->sex ] )
: strcpy( t, "someone" );
break;
case 's':
if ( actor )
can_see( mob, actor ) ? strcpy( t, his_her[ actor->sex ] )
: strcpy( t, "someone's" );
break;
case 'E':
if ( vict )
can_see( mob, vict ) ? strcpy( t, he_she[ vict->sex ] )
: strcpy( t, "someone" );
break;
case 'M':
if ( vict )
can_see( mob, vict ) ? strcpy( t, him_her[ vict->sex ] )
: strcpy( t, "someone" );
break;
case 'S':
if ( vict )
can_see( mob, vict ) ? strcpy( t, his_her[ vict->sex ] )
: strcpy( t, "someone's" );
break;
case 'j':
strcpy( t, he_she[ mob->sex ] );
break;
case 'k':
strcpy( t, him_her[ mob->sex ] );
break;
case 'l':
strcpy( t, his_her[ mob->sex ] );
break;
case 'J':
if ( rndm )
can_see( mob, rndm ) ? strcpy( t, he_she[ rndm->sex ] )
: strcpy( t, "someone" );
break;
case 'K':
if ( rndm )
can_see( mob, rndm ) ? strcpy( t, him_her[ rndm->sex ] )
: strcpy( t, "someone" );
break;
case 'L':
if ( rndm )
can_see( mob, rndm ) ? strcpy( t, his_her[ rndm->sex ] )
: strcpy( t, "someone's" );
break;
case 'o':
if ( obj )
can_see_obj( mob, obj ) ? one_argument( obj->name, t )
: strcpy( t, "something" );
break;
case 'O':
if ( obj )
can_see_obj( mob, obj ) ? strcpy( t, obj->short_descr )
: strcpy( t, "something" );
break;
case 'p':
if ( v_obj )
can_see_obj( mob, v_obj ) ? one_argument( v_obj->name, t )
: strcpy( t, "something" );
break;
case 'P':
if ( v_obj )
can_see_obj( mob, v_obj ) ? strcpy( t, v_obj->short_descr )
: strcpy( t, "something" );
break;
case 'a':
if ( obj )
switch ( *( obj->name ) )
{
case 'a': case 'e': case 'i':
case 'o': case 'u': strcpy( t, "an" );
break;
default: strcpy( t, "a" );
}
break;
case 'A':
if ( v_obj )
switch ( *( v_obj->name ) )
{
case 'a': case 'e': case 'i':
case 'o': case 'u': strcpy( t, "an" );
break;
default: strcpy( t, "a" );
}
break;
case '$':
strcpy( t, "$" );
break;
default:
bug( "Mob: %d bad $var", mob->pIndexData->vnum );
break;
}
return;
}
/* This procedure simply copies the cmnd to a buffer while expanding
* any variables by calling the translate procedure. The observant
* code scrutinizer will notice that this is taken from act()
*/
void mprog_process_cmnd( char *cmnd, CHAR_DATA *mob, CHAR_DATA *actor,
OBJ_DATA *obj, void *vo, CHAR_DATA *rndm, CHAR_DATA *evil )
{
char buf[ MAX_INPUT_LENGTH ];
char tmp[ MAX_INPUT_LENGTH ];
char *str;
char *i;
char *point;
point = buf;
str = cmnd;
while ( *str != '\0' )
{
if ( *str != '$' )
{
if ( *str == '\r' )
str++;
else
*point++ = *str++;
continue;
}
str++;
mprog_translate( *str, tmp, mob, actor, obj, vo, rndm, evil );
i = tmp;
++str;
while ( ( *point = *i ) != '\0' )
++point, ++i;
}
*point = '\0';
interpret( mob, buf );
return;
}
/* The main focus of the MudProgs. 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.
*/
void mprog_driver ( char *com_list, CHAR_DATA *mob, CHAR_DATA *actor,
OBJ_DATA *obj, void *vo)
{
char tmpcmndlst[ MAX_STRING_LENGTH ];
char buf [ MAX_INPUT_LENGTH ];
char *morebuf;
char *command_list;
char *cmnd;
CHAR_DATA *rndm = NULL;
CHAR_DATA *vch = NULL;
CHAR_DATA *evil = NULL;
int count = 0;
int max_evil = 999999;
if ( !mob )
{
bug( "MPDriver: NULL mob!" );
return;
}
if IS_AFFECTED( mob, AFF_CHARM )
return;
/* get a random visable mortal player who is in the room with the mob */
for ( vch = mob->in_room->people; vch; vch = vch->next_in_room )
if ( !IS_NPC( vch )
&& can_see( mob, vch ) )
{
if ( number_range( 0, count ) == 0 )
rndm = vch;
count++;
}
/* get the most evil visable mortal player who is in the room with the mob and is fighting */
for ( vch = mob->in_room->people; vch; vch = vch->next_in_room )
if ( !IS_NPC( vch )
&& can_see( mob, vch ) )
{
if ( vch->fighting && vch->alignment < max_evil )
{
max_evil = vch->alignment;
evil = vch;
}
}
strcpy( tmpcmndlst, com_list );
command_list = tmpcmndlst;
cmnd = command_list;
command_list = mprog_next_command( command_list );
while ( cmnd && *cmnd )
{
morebuf = one_argument( cmnd, buf );
if ( !str_cmp( buf, "if" ) )
command_list = mprog_process_if( morebuf, command_list, mob,
actor, obj, vo, rndm, evil );
else
mprog_process_cmnd( cmnd, mob, actor, obj, vo, rndm, evil );
cmnd = command_list;
command_list = mprog_next_command( command_list );
}
return;
}
/***************************************************************************
* Global function code and brief comments.
*/
/* 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, void *source, CHAR_DATA *actor,
OBJ_DATA *obj, void *vo, int trigger_type, int prog_type )
{
CHAR_DATA *pMob = NULL;
OBJ_DATA *pObj = NULL;
ROOM_INDEX_DATA *pRoom = NULL;
char temp1[ MAX_STRING_LENGTH ];
char temp2[ MAX_INPUT_LENGTH ];
char word[ MAX_INPUT_LENGTH ];
MPROG_DATA *mprg;
MPROG_LIST *pProgList = NULL;
char *list;
char *start;
char *dupl;
char *end;
unsigned int i;
switch(prog_type)
{
case MOB_PROG:
pMob = (CHAR_DATA *) source;
pProgList = pMob->pIndexData->mudprogs;
break;
case OBJ_PROG:
pObj = (OBJ_DATA *) source;
pMob = supermob;
pProgList = pObj->pIndexData->mudprogs;
break;
case ROOM_PROG:
pRoom = (ROOM_INDEX_DATA *) source;
pMob = supermob;
pProgList = pRoom->mudprogs;
break;
default:
break;
}
for ( ; pProgList; pProgList = pProgList->next )
if ( pProgList->mudprog->trigger_type & trigger_type )
{
mprg = pProgList->mudprog;
strcpy( temp1, mprg->arglist );
list = temp1;
for ( i = 0; i < strlen( list ); i++ )
list[i] = LOWER( list[i] );
strcpy( temp2, arg );
dupl = remove_color(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' ) )
{
if ( pMob == supermob )
set_supermob( source, prog_type );
mprog_driver( mprg->comlist, pMob, actor, obj, vo );
if ( pMob == supermob )
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' ) )
{
if ( pMob == supermob )
set_supermob( source, prog_type );
mprog_driver( mprg->comlist, pMob, actor, obj, vo );
if ( pMob == supermob )
release_supermob();
break;
}
else
dupl = start+1;
}
}
return;
}
bool mprog_percent_check( CHAR_DATA *mob, CHAR_DATA *actor, OBJ_DATA *obj,
void *vo, int trigger_type, int prog_type)
{
MPROG_LIST *pProgList;
bool executed = FALSE;
switch(prog_type)
{
case MOB_PROG:
for ( pProgList = mob->pIndexData->mudprogs; pProgList;
pProgList = pProgList->next )
if ( ( pProgList->mudprog->trigger_type & trigger_type )
&& ( number_percent( ) < atoi( pProgList->mudprog->arglist ) ) )
{
executed = TRUE;
mprog_driver( pProgList->mudprog->comlist, mob, actor, obj, vo );
if ( trigger_type != GREET_PROG && trigger_type != ALL_GREET_PROG )
break;
}
break;
case OBJ_PROG:
for ( pProgList = obj->pIndexData->mudprogs; pProgList;
pProgList = pProgList->next )
if ( ( pProgList->mudprog->trigger_type & trigger_type )
&& ( number_percent( ) <= atoi( pProgList->mudprog->arglist ) ) )
{
executed = TRUE;
mprog_driver( pProgList->mudprog->comlist, mob, actor, obj, vo );
if ( trigger_type != GREET_PROG )
break;
}
break;
case ROOM_PROG:
for ( pProgList = mob->in_room->mudprogs; pProgList;
pProgList = pProgList->next )
if ( ( pProgList->mudprog->trigger_type & trigger_type )
&& ( number_percent( ) <= atoi( pProgList->mudprog->arglist ) ) )
{
executed = TRUE;
mprog_driver( pProgList->mudprog->comlist, mob, actor, obj, vo );
if(trigger_type != ENTER_PROG)
break;
}
break;
default:
executed = FALSE;
break;
}
return executed;
}
/* 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;
MPROG_LIST *pProgList;
bool found = FALSE;
if ( IS_NPC( mob )
&& IS_SET( mob->pIndexData->progtypes, ACT_PROG ) )
{
if ( IS_NPC( ch ) && ch->pIndexData == mob->pIndexData )
return;
for ( pProgList = mob->pIndexData->mudprogs; pProgList; pProgList = pProgList->next )
if ( pProgList->mudprog->trigger_type & ACT_PROG )
{
found = TRUE;
break;
}
if ( !found )
return;
tmp_act = alloc_mem( sizeof( MPROG_ACT_LIST ) );
if ( mob->mpactnum > 0 )
tmp_act->next = mob->mpact;
else
tmp_act->next = NULL;
mob->mpact = tmp_act;
mob->mpact->buf = str_dup( buf );
mob->mpact->ch = ch;
mob->mpact->obj = obj;
mob->mpact->vo = vo;
mob->mpactnum++;
}
return;
}
void mprog_bribe_trigger( CHAR_DATA *mob, CHAR_DATA *ch, int amount )
{
char buf[ MAX_STRING_LENGTH ];
MPROG_LIST *pList;
OBJ_DATA *obj;
if ( IS_NPC( mob )
&& ( mob->pIndexData->progtypes & BRIBE_PROG ) )
{
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 );
free_string( obj->short_descr );
obj->short_descr = str_dup( buf );
obj->value[0] = amount;
obj_to_char( obj, mob );
mob->gold -= amount;
for ( pList = mob->pIndexData->mudprogs; pList; pList = pList->next )
if ( ( pList->mudprog->trigger_type & BRIBE_PROG )
&& ( amount >= atoi( pList->mudprog->arglist ) ) )
{
mprog_driver( pList->mudprog->comlist, mob, ch, obj, NULL );
break;
}
}
return;
}
void mprog_death_trigger( CHAR_DATA *mob )
{
if ( IS_NPC( mob )
&& ( mob->pIndexData->progtypes & DEATH_PROG ) )
{
mob->position = POS_RESTING;
mprog_percent_check( mob, NULL, NULL, NULL, DEATH_PROG, MOB_PROG );
mob->position = POS_DEAD;
}
else
{
death_cry( mob );
}
return;
}
void mprog_entry_trigger( CHAR_DATA *mob )
{
if ( IS_NPC( mob )
&& ( mob->pIndexData->progtypes & ENTRY_PROG ) )
mprog_percent_check( mob, NULL, NULL, NULL, ENTRY_PROG, MOB_PROG );
return;
}
void mprog_fight_trigger( CHAR_DATA *mob, CHAR_DATA *ch )
{
if ( IS_NPC( mob )
&& ( mob->pIndexData->progtypes & FIGHT_PROG ) )
{
if ( IS_NPC( ch ) && ch->pIndexData == mob->pIndexData )
return;
mprog_percent_check( mob, ch, NULL, NULL, FIGHT_PROG, MOB_PROG );
}
return;
}
void mprog_fightroom_trigger( CHAR_DATA *mob )
{
CHAR_DATA *victim;
if ( !mob || !mob->in_room )
return;
if ( IS_NPC( mob )
&& ( mob->pIndexData->progtypes & FIGHTROOM_PROG ) )
{
for ( victim = mob->in_room->people; victim; victim = victim->next_in_room )
{
if ( victim != mob && victim->fighting == mob
&& mprog_percent_check( mob, victim, NULL, NULL, FIGHTROOM_PROG, MOB_PROG ) )
break;
}
}
return;
}
void mprog_give_trigger( CHAR_DATA *mob, CHAR_DATA *ch, OBJ_DATA *obj )
{
char buf[MAX_INPUT_LENGTH];
MPROG_LIST *pList;
if ( IS_NPC( mob )
&& ( mob->pIndexData->progtypes & GIVE_PROG ) )
{
if ( IS_NPC( ch ) && ch->pIndexData == mob->pIndexData )
return;
for ( pList = mob->pIndexData->mudprogs; pList; pList = pList->next )
{
one_argument( pList->mudprog->arglist, buf );
if ( ( pList->mudprog->trigger_type & GIVE_PROG )
&& ( ( !str_cmp( obj->name, pList->mudprog->arglist ) )
|| ( !str_cmp( "all", buf ) ) ) )
{
mprog_driver( pList->mudprog->comlist, mob, ch, obj, NULL );
break;
}
}
}
return;
}
void mprog_greet_trigger( CHAR_DATA *ch )
{
CHAR_DATA *vmob;
if ( IS_NPC( ch ) )
return;
for ( vmob = ch->in_room->people; vmob; vmob = vmob->next_in_room )
if ( IS_NPC( vmob )
&& ch != vmob
&& can_see( vmob, ch )
&& ( !vmob->fighting )
&& IS_AWAKE( vmob )
&& ( vmob->pIndexData->progtypes & GREET_PROG) )
mprog_percent_check( vmob, ch, NULL, NULL, GREET_PROG, MOB_PROG );
else if ( IS_NPC( vmob )
&& ( !vmob->fighting )
&& IS_AWAKE( vmob )
&& ( vmob->pIndexData->progtypes & ALL_GREET_PROG ) )
mprog_percent_check(vmob,ch,NULL,NULL,ALL_GREET_PROG, MOB_PROG );
return;
}
void mprog_hitprcnt_trigger( CHAR_DATA *mob, CHAR_DATA *ch)
{
MPROG_LIST *pList;
if ( IS_NPC( mob )
&& ( mob->pIndexData->progtypes & HITPRCNT_PROG ) )
{
if ( IS_NPC( ch ) && ch->pIndexData == mob->pIndexData )
return;
for ( pList = mob->pIndexData->mudprogs; pList; pList = pList->next )
if ( ( pList->mudprog->trigger_type & HITPRCNT_PROG )
&& ( ( 100*mob->hit / mob->max_hit ) < atoi( pList->mudprog->arglist ) ) )
{
mprog_driver( pList->mudprog->comlist, mob, ch, NULL, NULL );
break;
}
}
return;
}
void mprog_random_trigger( CHAR_DATA *mob )
{
if ( mob->pIndexData->progtypes & RAND_PROG)
mprog_percent_check(mob,NULL,NULL,NULL,RAND_PROG, MOB_PROG);
return;
}
void mprog_speech_trigger( char *txt, CHAR_DATA *actor )
{
CHAR_DATA *vmob;
for ( vmob = actor->in_room->people; vmob; vmob = vmob->next_in_room )
if ( IS_NPC( vmob ) && ( vmob->pIndexData->progtypes & SPEECH_PROG ) )
{
if ( IS_NPC( actor ) && ( vmob->pIndexData == actor->pIndexData ) )
continue;
mprog_wordlist_check( txt, vmob, actor, NULL, NULL, SPEECH_PROG, MOB_PROG );
}
return;
}
/* Written by Zak, Jan 13/1998
* Goes in interpret() before regular command parsing.
* This function checks all mobs in room with the character for a command
* trigger matching what the character typed.
* The function returns TRUE if the character's command should be run
* through the regular interpreter too. */
bool mprog_command_trigger (char *txt, CHAR_DATA *ch)
{
char *argument;
char arg [MAX_INPUT_LENGTH];/* I'm assuming that the cmd_table won't
* ever have a command longer than
* MAX_INPUT_LENGTH */
CHAR_DATA *vmob;
OBJ_DATA *obj;
ROOM_INDEX_DATA *room;
MPROG_LIST *pList;
int cmd;
bool can_do = TRUE;
argument = strdup(txt);
/* First check for the command typed being a prefix of anything in
* the regular command table, and expand it to the full command. */
argument = one_argument( argument, arg );
for (cmd=0; cmd_table[cmd].name[0] != '\0'; cmd++)
{
if (arg[0] == cmd_table[cmd].name[0] &&
!str_prefix( arg, cmd_table[cmd].name ) )
{
strncpy(arg,cmd_table[cmd].name,sizeof(arg));
break;
}
}
/* Find mobs that are in_room that have a COMMAND_PROG */
for ( vmob = ch->in_room->people; vmob; vmob = vmob->next_in_room )
if ( IS_NPC( vmob ) && ( vmob->pIndexData->progtypes & COMMAND_PROG ) )
{
for ( pList = vmob->pIndexData->mudprogs; pList; pList = pList->next )
{
if ( ( pList->mudprog->trigger_type & COMMAND_PROG ) &&
(!str_cmp(pList->mudprog->arglist,arg)) )
{
mprog_driver( pList->mudprog->comlist, vmob, ch, NULL, NULL );
can_do = FALSE;
}
}
}
/* Obj and Room command_prog support by Kyle Boyd */
/* objs in inventory and worn... */
for ( obj = ch->carrying; obj; obj = obj->next_content )
if ( obj->pIndexData->progtypes & COMMAND_PROG )
{
for ( pList = obj->pIndexData->mudprogs; pList; pList = pList->next )
{
if ( (pList->mudprog->trigger_type & COMMAND_PROG) &&
(!str_cmp(pList->mudprog->arglist,arg)) )
{
set_supermob( obj, OBJ_PROG );
mprog_driver( pList->mudprog->comlist, supermob, ch, obj, NULL );
release_supermob();
can_do = FALSE;
}
}
}
/* objs in room... */
for ( obj = ch->in_room->contents; obj; obj = obj->next_content )
if ( obj->pIndexData->progtypes & COMMAND_PROG )
{
for ( pList = vmob->pIndexData->mudprogs; pList; pList = pList->next)
{
if ( (pList->mudprog->trigger_type & COMMAND_PROG) &&
(!str_cmp(pList->mudprog->arglist,arg)) )
{
set_supermob( obj, OBJ_PROG );
mprog_driver( pList->mudprog->comlist, supermob, ch, obj, NULL );
release_supermob();
can_do = FALSE;
}
}
}
/* And finally, room progs */
room = ch->in_room;
if ( room->progtypes & COMMAND_PROG )
{
for ( pList = room->mudprogs; pList; pList = pList->next)
{
if ( (pList->mudprog->trigger_type & COMMAND_PROG) &&
(!str_cmp(pList->mudprog->arglist,arg)) )
{
set_supermob( room, ROOM_PROG );
mprog_driver( pList->mudprog->comlist, supermob, ch, NULL, NULL );
release_supermob();
can_do = FALSE;
}
}
}
return can_do;
}
/*****************************************************************
* ROOM PROG SUPPORT STARTS HERE: *
* most of this code was taken from the SMAUG code base *
* with modifications made to fit our mud... *
*****************************************************************/
void init_supermob( )
{
supermob = create_mobile( get_mob_index(MOB_VNUM_SUPERMOB) );
char_to_room( supermob, get_room_index(ROOM_VNUM_SUPERMOB) );
return;
}
void set_supermob( void *source, int prog_type )
{
OBJ_DATA *pObj = NULL;
ROOM_INDEX_DATA *pRoom = NULL;
OBJ_DATA *in_obj = NULL;
char buf[200];
if ( !supermob )
{
supermob = create_mobile(get_mob_index( MOB_VNUM_SUPERMOB ));
char_to_room( supermob, get_room_index(ROOM_VNUM_SUPERMOB) );
}
if(!source)
return;
switch(prog_type)
{
case OBJ_PROG:
pObj = (OBJ_DATA *) source;
for ( in_obj = pObj; in_obj->in_obj; in_obj = in_obj->in_obj )
;
if ( in_obj->carried_by )
pRoom = in_obj->carried_by->in_room;
else
pRoom = pObj->in_room;
if( !pRoom )
return;
if (supermob->short_descr)
free_string(supermob->short_descr);
supermob->short_descr = str_dup(pObj->short_descr);
/* Added by Jenny to allow bug messages to show the vnum
of the object, and not just supermob's vnum */
sprintf( buf, "Object #%d", pObj->pIndexData->vnum );
free_string( supermob->description );
supermob->description = str_dup( buf );
break;
case ROOM_PROG:
pRoom = (ROOM_INDEX_DATA *) source;
if ( supermob->short_descr )
free_string(supermob->short_descr);
supermob->short_descr = str_dup(pRoom->name);
if ( supermob->name )
free_string(supermob->name);
supermob->name = str_dup(pRoom->name);
/* Added by Jenny to allow bug messages to show the vnum
of the room, and not just supermob's vnum */
sprintf( buf, "Room #%d", pRoom->vnum );
if ( supermob->description )
free_string( supermob->description );
supermob->description = str_dup( buf );
break;
}
char_from_room (supermob );
char_to_room( supermob, pRoom);
return;
}
void release_supermob( )
{
char_from_room( supermob );
if ( supermob->name )
free_string( supermob->name );
supermob->name = str_dup("SuperMob");
char_to_room( supermob, get_room_index( ROOM_VNUM_SUPERMOB ) );
}
/*
* Triggers follow
*/
void rprog_act_trigger( char *buf, ROOM_INDEX_DATA *room, CHAR_DATA *ch,
OBJ_DATA *obj, void *vo )
{
if ( room->progtypes & ACT_PROG )
{
MPROG_ACT_LIST *tmp_act;
/* supermob can't trigger it's own mprog */
if ( IS_NPC(ch) && ch->pIndexData == supermob->pIndexData )
return;
tmp_act = alloc_mem( sizeof( MPROG_ACT_LIST ) );
if ( room->mpactnum > 0 )
tmp_act->next = room->mpact;
else
tmp_act->next = NULL;
room->mpact = tmp_act;
room->mpact->buf = str_dup(buf);
room->mpact->ch = ch;
room->mpact->obj = obj;
room->mpact->vo = vo;
room->mpactnum++;
room_act_add(room);
}
return;
}
/*
*
*/
void rprog_leave_trigger( CHAR_DATA *ch )
{
if( ch->in_room && ch->in_room->progtypes & LEAVE_PROG )
{
set_supermob( ch->in_room, ROOM_PROG );
mprog_percent_check( supermob, ch, NULL, NULL, LEAVE_PROG, ROOM_PROG );
release_supermob();
}
return;
}
void rprog_enter_trigger( CHAR_DATA *ch )
{
if( ch->in_room && ch->in_room->progtypes & ENTER_PROG )
{
set_supermob( ch->in_room, ROOM_PROG );
mprog_percent_check( supermob, ch, NULL, NULL, ENTRY_PROG, ROOM_PROG );
release_supermob();
}
return;
}
void rprog_sleep_trigger( CHAR_DATA *ch )
{
if( ch->in_room && ch->in_room->progtypes & SLEEP_PROG )
{
set_supermob( ch->in_room, ROOM_PROG );
mprog_percent_check( supermob, ch, NULL, NULL, SLEEP_PROG, ROOM_PROG );
release_supermob();
}
return;
}
void rprog_rest_trigger( CHAR_DATA *ch )
{
if( ch->in_room && ch->in_room->progtypes & REST_PROG )
{
set_supermob( ch->in_room, ROOM_PROG );
mprog_percent_check( supermob, ch, NULL, NULL, REST_PROG, ROOM_PROG );
release_supermob();
}
return;
}
void rprog_rfight_trigger( CHAR_DATA *ch )
{
if( ch->in_room && ch->in_room->progtypes & RFIGHT_PROG )
{
set_supermob( ch->in_room, ROOM_PROG );
mprog_percent_check( supermob, ch, NULL, NULL, RFIGHT_PROG, ROOM_PROG );
release_supermob();
}
return;
}
void rprog_death_trigger( CHAR_DATA *ch )
{
if( ch->in_room && ch->in_room->progtypes & RDEATH_PROG )
{
set_supermob( ch->in_room, ROOM_PROG );
mprog_percent_check( supermob, ch, NULL, NULL, RDEATH_PROG, ROOM_PROG );
release_supermob();
}
return;
}
void rprog_speech_trigger( char *txt, CHAR_DATA *ch )
{
/* prevent circular triggers by not allowing mob to trigger itself */
if ( IS_NPC(ch) && ch->pIndexData == supermob->pIndexData )
return;
if( ch->in_room && ch->in_room->progtypes & SPEECH_PROG )
{
/* supermob is set and released in mprog_wordlist_check */
mprog_wordlist_check( txt, ch->in_room, ch, NULL, NULL, SPEECH_PROG, ROOM_PROG );
}
return;
}
void rprog_random_trigger( CHAR_DATA *ch )
{
if ( ch->in_room && ch->in_room->progtypes & RAND_PROG)
{
set_supermob( ch->in_room, ROOM_PROG );
mprog_percent_check(supermob,ch,NULL,NULL,RAND_PROG, ROOM_PROG);
release_supermob();
}
return;
}
/* Written by Jenny, Nov 29/95 */
void progbug( char *str, CHAR_DATA *mob )
{
/* Check if we're dealing with supermob, which means the bug occurred
in a room or obj prog. */
if ( mob->pIndexData->vnum == MOB_VNUM_SUPERMOB )
{
/* It's supermob. In set_supermob the description
was set to indicate the object or room, so we just need to show
the description in the bug message. */
bug( "%s, %s.", str,
!mob->description ? "(unknown)" : mob->description );
}
else
{
bug( "%s, Mob #%d.", str, mob->pIndexData->vnum );
}
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;
for ( runner = room_act_list; runner; runner = runner->next )
if ( runner->vo == room )
return;
runner = alloc_mem( sizeof(*runner) );
runner->vo = room;
runner->next = room_act_list;
room_act_list = runner;
}
void room_act_update( void )
{
struct act_prog_data *runner;
MPROG_ACT_LIST *mpact;
while ( (runner = room_act_list) )
{
ROOM_INDEX_DATA *room = runner->vo;
while ( (mpact = room->mpact) )
{
if ( mpact->ch->in_room == room )
mprog_wordlist_check(mpact->buf, room, mpact->ch, mpact->obj,
mpact->vo, ACT_PROG, ROOM_PROG);
room->mpact = mpact->next;
free_string( mpact->buf );
free_mem( mpact, sizeof(*mpact) );
}
room->mpact = NULL;
room->mpactnum = 0;
room_act_list = runner->next;
free_mem( runner, sizeof(*runner) );
}
return;
}
/*****************************************************************
* OBJECT PROG SUPPORT STARTS HERE: *
* most of this code was taken from the SMAUG code base *
* with modifications made to fit our mud... *
*****************************************************************/
/*
* Triggers follow
*/
void oprog_greet_trigger( CHAR_DATA *ch )
{
OBJ_DATA *vobj;
for ( vobj=ch->in_room->contents; vobj; vobj = vobj->next_content )
if ( vobj->pIndexData->progtypes & GREET_PROG )
{
set_supermob( vobj, OBJ_PROG ); /* not very efficient to do here */
mprog_percent_check( supermob, ch, vobj, NULL, GREET_PROG, OBJ_PROG );
release_supermob();
}
return;
}
void oprog_speech_trigger( char *txt, CHAR_DATA *ch )
{
OBJ_DATA *vobj;
/* supermob is set and released in mprog_wordlist_check */
for ( vobj=ch->in_room->contents; vobj; vobj = vobj->next_content )
if ( vobj->pIndexData->progtypes & SPEECH_PROG )
{
mprog_wordlist_check( txt, vobj, ch, vobj, NULL, SPEECH_PROG, OBJ_PROG );
}
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 ( obj->pIndexData->progtypes & RAND_PROG)
{
set_supermob( obj, OBJ_PROG );
mprog_percent_check(supermob,NULL,obj,NULL,RAND_PROG, OBJ_PROG);
release_supermob();
}
return;
}
/*
* in wear_obj, between each successful equip_char
* the subsequent return
*/
void oprog_wear_trigger( CHAR_DATA *ch, OBJ_DATA *obj )
{
if ( obj->pIndexData->progtypes & WEAR_PROG )
{
set_supermob( obj, OBJ_PROG );
mprog_percent_check( supermob, ch, obj, NULL, WEAR_PROG, OBJ_PROG );
release_supermob();
}
return;
}
bool oprog_use_trigger( CHAR_DATA *ch, OBJ_DATA *obj, CHAR_DATA *vict,
OBJ_DATA *targ, void *vo )
{
bool executed = FALSE;
if ( obj->pIndexData->progtypes & USE_PROG )
{
set_supermob( obj, OBJ_PROG );
if ( obj->item_type == ITEM_STAFF )
{
if ( vict )
executed = mprog_percent_check( supermob, ch, obj, vict, USE_PROG, OBJ_PROG );
else
executed = mprog_percent_check( supermob, ch, obj, targ, USE_PROG, OBJ_PROG );
}
else
{
executed = mprog_percent_check( supermob, ch, obj, NULL, USE_PROG, OBJ_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 ( obj->pIndexData->progtypes & REMOVE_PROG )
{
set_supermob( obj, OBJ_PROG );
mprog_percent_check( supermob, ch, obj, NULL, REMOVE_PROG, OBJ_PROG );
release_supermob();
}
return;
}
/*
* call in do_sac, right before extract_obj
*/
void oprog_sac_trigger( CHAR_DATA *ch, OBJ_DATA *obj )
{
if ( obj->pIndexData->progtypes & SAC_PROG )
{
set_supermob( obj, OBJ_PROG );
mprog_percent_check( supermob, ch, obj, NULL, SAC_PROG, OBJ_PROG );
release_supermob();
}
return;
}
/*
* 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 ( obj->pIndexData->progtypes & GET_PROG )
{
set_supermob( obj, OBJ_PROG );
mprog_percent_check( supermob, ch, obj, NULL, GET_PROG, OBJ_PROG );
release_supermob();
}
return;
}
/*
* called in damage_obj in act_obj.c
*/
void oprog_damage_trigger( CHAR_DATA *ch, OBJ_DATA *obj )
{
if ( obj->pIndexData->progtypes & DAMAGE_PROG )
{
set_supermob( obj, OBJ_PROG );
mprog_percent_check( supermob, ch, obj, NULL, DAMAGE_PROG, OBJ_PROG );
release_supermob();
}
return;
}
/*
* called in do_repair in shops.c
*/
void oprog_repair_trigger( CHAR_DATA *ch, OBJ_DATA *obj )
{
if ( obj->pIndexData->progtypes & REPAIR_PROG )
{
set_supermob( obj, OBJ_PROG );
mprog_percent_check( supermob, ch, obj, NULL, REPAIR_PROG, OBJ_PROG );
release_supermob();
}
return;
}
/*
* 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 ( obj->pIndexData->progtypes & DROP_PROG )
{
set_supermob( obj, OBJ_PROG );
mprog_percent_check( supermob, ch, obj, NULL, DROP_PROG, OBJ_PROG );
release_supermob();
}
return;
}
/*
* call towards end of do_examine, right before check_for_trap
*/
void oprog_examine_trigger( CHAR_DATA *ch, OBJ_DATA *obj )
{
if ( obj->pIndexData->progtypes & EXA_PROG )
{
set_supermob( obj, OBJ_PROG );
mprog_percent_check( supermob, ch, obj, NULL, EXA_PROG, OBJ_PROG );
release_supermob();
}
return;
}
/*
* call in fight.c, group_gain, after (?) the obj_to_room
*/
void oprog_zap_trigger( CHAR_DATA *ch, OBJ_DATA *obj )
{
if ( obj->pIndexData->progtypes & ZAP_PROG )
{
set_supermob( obj, OBJ_PROG );
mprog_percent_check( supermob, ch, obj, NULL, ZAP_PROG, OBJ_PROG );
release_supermob();
}
return;
}
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 ( IS_NPC(ch) && ch->pIndexData == supermob->pIndexData )
return; /* prevent supermob from triggering itself */
if ( mobj->pIndexData->progtypes & ACT_PROG )
{
MPROG_ACT_LIST *tmp_act;
tmp_act = alloc_mem( sizeof(MPROG_ACT_LIST) );
if ( mobj->mpactnum > 0 )
tmp_act->next = mobj->mpact;
else
tmp_act->next = NULL;
mobj->mpact = tmp_act;
mobj->mpact->buf = str_dup(buf);
mobj->mpact->ch = ch;
mobj->mpact->obj = obj;
mobj->mpact->vo = vo;
mobj->mpactnum++;
obj_act_add(mobj);
}
return;
}
void obj_act_add( OBJ_DATA *obj )
{
struct act_prog_data *runner;
for ( runner = obj_act_list; runner; runner = runner->next )
if ( runner->vo == obj )
return;
runner = alloc_mem( sizeof(*runner) );
runner->vo = obj;
runner->next = obj_act_list;
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 )
{
mprog_wordlist_check(mpact->buf, obj, mpact->ch, mpact->obj,
mpact->vo, ACT_PROG, OBJ_PROG);
obj->mpact = mpact->next;
free_string(mpact->buf);
free_mem(mpact, sizeof(*mpact) );
}
obj->mpact = NULL;
obj->mpactnum = 0;
obj_act_list = runner->next;
free_mem(runner, sizeof(*runner));
}
return;
}
/*
* call in fight.c, one_hit and second_one_hit at the end.
*/
void oprog_hit_trigger( CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA *obj )
{
if ( obj->pIndexData->progtypes & HIT_PROG )
{
set_supermob( obj, OBJ_PROG );
mprog_percent_check( supermob, ch, obj, victim, HIT_PROG, OBJ_PROG );
release_supermob();
}
return;
}