This snippet makes three major changes to standard SMAUG MUD-Progs.
1. You become capable of using tokens as RVALS
2. You gain the ability to expose actual attributes of tokens rather than just their names.
3. You gain the ability to set and recall tokens $1 through $5 within the scope of any script.
Some simple examples to clarify:
Script:
>speech_prog test
say Hi $n, you're a $n.race.
'You might even be a $n.class.
Output:
You say 'test'
Puff says 'Hi Eos, you're a pixie.'
Puff says 'You might even be a druid.'
Script:
>speech_prog bleh
setvar 1 murp
say $1
OutPut:
You say 'bleh'
Puff says 'murp'
Script:
>speech_prog thirdtry
setvar 1 $n.race
if race($i) == $1
say Hey look we're the same race!
else
say Aw. You're a different species.
endif
OutPut:
mset puff race dragon
You say 'thirdtry'
Puff says 'Aw. You're a different species.'
mset puff race pixie
You say 'thirdtry'
Puff says 'Hey look we're the same race!'
In db.c after:
void mprog_read_programs(
FILE * fp, MOB_INDEX_DATA * pMobIndex
);
void oprog_read_programs( FILE * fp, OBJ_INDEX_DATA * pObjIndex );
void rprog_read_programs( FILE * fp, ROOM_INDEX_DATA * pRoomIndex
);
Add:
void reset_variables(
void );
After:
/*
* Globals.
*/
load_weatherdata( );
init_area_weather( );
Add:
reset_variables();
In mud.h after:
typedef struct lcnv_data LCNV_DATA;
typedef struct lang_data LANG_DATA;
typedef struct specfun_list SPEC_LIST;
Add:
typedef struct variable_data VARIABLE_DATA; /* Mud Prog
Variables - Eos */
Before:
/*
* Ban Types --- Shaddai
*/
Add:
/* Mud Prog Variables - Eos */
struct variable_data
{
char *v1;
char *v2;
char *v3;
char *v4;
char *v5;
};
After:
extern short gsn_halfling;
Add:
/*
Mud Prog Variables -
Eos
*/
extern struct
variable_data variable;
In mud_prog.c
After:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "mud.h"
Add
#include <stdarg.h>
VARIABLE_DATA variable;
void reset_variables( void );
char *parse_setvar( char *cmnd,
CHAR_DATA *mob, CHAR_DATA *actor, OBJ_DATA *obj, void
*vo, CHAR_DATA *rndm );
void add_letter( char *string, char letter);
char *rval_translate( char *rval,
CHAR_DATA *mob, CHAR_DATA *actor, OBJ_DATA *obj, void
*vo, CHAR_DATA *rndm );
void stralloc_printf( char **pointer, char *fmt, ...);
char *format( char *fmt, ...);
Then After:
/*
* Recursive function used by the carryingvnum ifcheck.
* It loops thru all objects belonging to a char (in nested containers)
{
switch ( cvar[1]
)
{
Add:
case
'1':
case '2':
case '3':
case '4':
case '5':
chkchar = actor;
break;
After
if( !chkchar && !chkobj )
return BERR;
Add:
rval =
rval_translate(rval, mob,
actor, obj, vo, rndm);
if ( !str_cmp(chck, "var1") )
{
bug(
"setvar %s", rval);
if (is_number(rval))
return mprog_veval(atoi(variable.v1),
opr, atoi(rval), mob);
if (!str_cmp(variable.v1, rval))
return TRUE;
return
FALSE;
}
if ( !str_cmp(chck, "var2") )
{
if (is_number(rval))
return mprog_veval(atoi(variable.v2),
opr, atoi(rval), mob);
if (!str_cmp(variable.v2, rval))
return TRUE;
return
FALSE;
}
if ( !str_cmp(chck, "var3") )
{
if (is_number(rval))
return mprog_veval(atoi(variable.v3),
opr, atoi(rval), mob);
if (!str_cmp(variable.v3, rval))
return TRUE;
return
FALSE;
}
if ( !str_cmp(chck, "var4") )
{
if (is_number(rval))
return mprog_veval(atoi(variable.v4),
opr, atoi(rval), mob);
if (!str_cmp(variable.v4, rval))
return TRUE;
return
FALSE;
}
if ( !str_cmp(chck, "var5") )
{
if (is_number(rval))
return mprog_veval(atoi(variable.v5),
opr, atoi(rval), mob);
if (!str_cmp(variable.v5, rval))
return TRUE;
return
FALSE;
}
Between:
switch ( ch
)
{
And
case 'i':
if( mob && !char_died( mob ) )
{
Add:
case '1':
strcpy(
t, variable.v1 );
break;
case '2':
strcpy(
t, variable.v2 );
break;
case '3':
strcpy(
t, variable.v3 );
break;
case '4':
strcpy(
t, variable.v4 );
break;
case '5':
strcpy(
t, variable.v5 );
break;
Above:
iflevel = 0;
Add:
reset_variables();
Replace:
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 );
With:
vnum = mob->pIndexData->vnum;
point = buf;
str = cmnd;
str = parse_setvar( str, mob, actor, obj, vo, rndm );
/* 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';
/* This is where to add in the check for "setvar"
*/
if ( !str_cmp( firstword,
"setvar" ) )
{
short var;
char *newtext;
/* does not make it past this point, explore why */
newtext = buf;
newtext = one_argument(
newtext, firstword );
newtext = one_argument(
newtext, firstword );
var = atoi(firstword);
str = cmnd;
switch(var)
{
default:
bug( "Unknown setvar
%s:%d", firstword,
mob->pIndexData->vnum
);
return BERR;
case 1:
stralloc_printf(
&variable.v1, "%s", newtext);
break;
case 2:
stralloc_printf(
&variable.v2, "%s", newtext);
break;
case 3:
stralloc_printf(
&variable.v3, "%s", newtext);
break;
case 4:
stralloc_printf(
&variable.v4, "%s", newtext);
break;
case 5:
stralloc_printf(
&variable.v5, "%s", newtext);
break;
}
}
interpret( mob, buf );
Finally at the bottom of the file add in all of this:
char *rval_translate( char *rval, CHAR_DATA *mob, CHAR_DATA *actor, OBJ_DATA *obj, void *vo, CHAR_DATA *rndm )
{
CHAR_DATA *ch=NULL;
OBJ_DATA *obj2=NULL;
if (rval[0] != '$')
return rval;
switch(rval[1])
{
case 'i':
ch =
mob;
break;
case
'n': ch =
actor;
break;
case
't': ch = (CHAR_DATA *)vo; break;
case
'r': ch = rndm;
break;
case
'o': obj2 = obj;
break;
case
'p': obj2 = (OBJ_DATA *)vo;
break;
case
'1':
return variable.v1;
case '2':
return variable.v2;
case
'3':
return variable.v3;
case
'4':
return variable.v4;
case
'5':
return variable.v5;
default:
break;
}
if (ch)
return IS_NPC(ch) ? ch->short_descr : ch->name;
if (obj2)
return obj2->short_descr;
return "Tell a Staff Member you got this result and
how";
}
void reset_variables()
{
stralloc_printf( &variable.v1,
"%s", "Unset");
stralloc_printf( &variable.v2,
"%s", "Unset");
stralloc_printf( &variable.v3,
"%s", "Unset");
stralloc_printf( &variable.v4,
"%s", "Unset");
stralloc_printf( &variable.v5,
"%s", "Unset");
return;
}
char *parse_setvar( char *cmnd,
CHAR_DATA *mob, CHAR_DATA *actor, OBJ_DATA *obj, void
*vo, CHAR_DATA *rndm )
{
static char results[MAX_STRING_LENGTH*2];
int x;
CHAR_DATA *chkchar = NULL;
OBJ_DATA *chkobj = NULL;
results[0] = '\0';
for ( x=0; cmnd[x] != '\0'; x++)
{
chkchar = NULL;
chkobj = NULL;
if (cmnd[x] == '\0')
return results;
if (cmnd[x] != '$')
add_letter( results, cmnd[x]);
else
{
switch(cmnd[x+1])
{
default:
add_letter( results, cmnd[x]);
// Because the next letter is not a $ it will just take care of itself
break;
case 'i':
chkchar = mob;
break;
case 'n':
chkchar = actor;
if (!chkchar) // Used
$n where they should've $r'd
chkchar = rndm;
break;
case 't':
chkchar = (CHAR_DATA *)vo;
if (!chkchar) // Used $t where $t was impossible.
chkchar = actor; //
can use actor or rndm as you prefer
break;
case 'r':
chkchar = rndm;
if (!chkchar)
chkchar = actor; //
Used $r where they should've $n'd
break;
case 'o':
chkobj = obj;
break;
case 'p':
chkobj = (OBJ_DATA *)vo;
break;
}
}
if (chkchar || chkobj)
// Ok, so one of them is valid, lets find out what the info we're looking at
is.
{
x+=2; // skip over the identifier and go
straight into whats next...
if (cmnd[x] != '.' || cmnd[x] == '\0') // not a period, so this isnt a pointer, just a variable.
{
add_letter(
results, cmnd[x-2]); // Put this piece back
add_letter(
results, cmnd[x-1]); // Put this piece back
add_letter(
results, cmnd[x]); // Put this piece back
if ( cmnd[x] ==
'\0')
return results;
continue; // and keep going.
}
else // Ok, they used the right syntax,
lets fight out what our 'word' is.
{
char word[MAX_INPUT_LENGTH];;
word[0] = '\0';
x++;
while ( isalpha(cmnd[x]) && cmnd[x] !=
'\0') // Lets find the next single word.
{
add_letter( word, cmnd[x]);
x++;
}
// If we get here,
we assume we now have the word.
if (chkchar
!= NULL) // Begin looking for possible character matches.
{
if (!str_cmp( word, "name"))
{
if (IS_NPC(chkchar))
strcat( results, format( "%s", chkchar->short_descr) );
else
strcat( results, format( "%s", chkchar->name ));
}
if (!str_cmp( word, "sex"))
{
if (chkchar->sex == 2)
strcat( results, format( "%s",
"female" ));
else
strcat( results, format( "%s",
"male" ));
}
if (!str_cmp( word, "class"))
{
strcat( results,
format( "%s", npc_class[chkchar->Class]
));
}
if (!str_cmp( word, "race"))
{
strcat( results, get_race(chkchar) );
}
if (!str_cmp( word, "level"))
{
strcat( results, format( "%d", chkchar->level) );
}
// add
your own char checks at this point
}
if (chkobj
!= NULL) // Then do objects.
{
if (!str_cmp( word, "level"))
{
strcat( results, format( "%d", chkobj->level) );
}
// add
your own obj checks at this point
}
if (cmnd[x]
== '\0')
return results;
else
add_letter(
results, cmnd[x]);
}
}
}
return results;
}
void add_letter( char *string, char letter)
{
char buf[MAX_INPUT_LENGTH];
sprintf(buf,
"%c", letter);
strcat(string, buf);
return;
}
void stralloc_printf( char **pointer, char *fmt, ...)
{
char buf[MAX_STRING_LENGTH*2];/*
better safe than sorry */
va_list args;
va_start(args,
fmt);
vsprintf(buf,
fmt, args);
va_end(args);
if (*pointer)
STRFREE(*pointer);
*pointer = STRALLOC( buf);
return;
}
char *format( char *fmt, ...)
{
static char newstring[MAX_INPUT_LENGTH];
char buf[MAX_STRING_LENGTH*2];
/* better safe than sorry */
va_list args;
newstring[0] = '\0';
if (fmt[0] == '\0')
return " ";
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
if (buf[0] == '\0')
return " ";
strcpy( newstring, buf);
return newstring;
}