/**************************************************************************** * [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, Fireblade, Edmond, Conran | * * ------------------------------------------------------------------------ * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * ------------------------------------------------------------------------ * * Variable Handling Module (Thoric) * ****************************************************************************/ #include <ctype.h> #include <stdio.h> #include <string.h> #include <time.h> #include "mud.h" #ifdef USE_IMC #include "imc-mercbase.h" #include "icec-mercbase.h" #endif #if defined(KEY) #undef KEY #endif #define KEY( literal, field, value ) \ if ( !str_cmp( word, literal ) ) \ { \ field = value; \ fMatch = TRUE; \ break; \ } VARIABLE_DATA *make_variable(char type, int vnum, char *tag) { VARIABLE_DATA *var; CREATE(var, VARIABLE_DATA, 1); var->next = NULL; var->type = type; var->flags = 0; var->vnum = vnum; var->tag = str_dup(tag); var->c_time = current_time; var->m_time = current_time; var->r_time = 0; var->timer = 0; switch(type) { case vtINT: var->data = NULL; break; case vtXBIT: CREATE(var->data, EXT_BV, 1); break; case vtSTR: var->data = NULL; } return var; } void delete_vdata(VARIABLE_DATA *var) { switch(var->type) { case vtXBIT: case vtSTR: if ( var->data ) DISPOSE(var->data); break; } } void delete_variable(VARIABLE_DATA *var) { delete_vdata(var); DISPOSE(var->tag); DISPOSE(var); } /* * Return the specified tag from a character */ VARIABLE_DATA *get_tag(CHAR_DATA *ch, char *tag, int vnum) { VARIABLE_DATA *vd; for ( vd = ch->variables; vd; vd = vd->next ) if ( (!vnum || vnum == vd->vnum) && !str_cmp(tag, vd->tag) ) return vd; return NULL; } /* * Remove the specified tag from a character */ bool remove_tag(CHAR_DATA *ch, char *tag, int vnum) { VARIABLE_DATA *vd_next, *vd = ch->variables; if ( !vd ) return FALSE; if ( (!vnum || vnum == vd->vnum) && !str_cmp(tag, vd->tag) ) { ch->variables = vd->next; delete_variable(vd); return TRUE; } for ( ; vd && vd->next; vd = vd_next ) { vd_next = vd->next; if ( (!vnum || vnum == vd_next->vnum) && !str_cmp(tag, vd_next->tag) ) { vd->next = vd_next->next; delete_variable(vd_next); return TRUE; } } return FALSE; } /* * Tag a variable onto a character Will replace if specified to do so, * otherwise if already exists, fail */ int tag_char(CHAR_DATA *ch, VARIABLE_DATA *var, int replace) { VARIABLE_DATA *vd, *pvd; bool found = FALSE; pvd = vd = ch->variables; for ( ; vd; vd = vd->next ) { if ( vd == var ) /* same variable -- leave it be */ { var->m_time = current_time; return 0; } if ( vd->vnum == var->vnum && !str_cmp(vd->tag, var->tag) ) { if ( !replace ) return -1; found = TRUE; break; } pvd = vd; } if ( found ) { var->m_time = current_time; var->c_time = vd->c_time; var->r_time = vd->r_time; var->next = vd->next; if ( vd == ch->variables ) ch->variables = var; else pvd->next = var; delete_variable(vd); return 0; } var->next = ch->variables; ch->variables = var; return 0; } bool is_valid_tag(const char *tagname) { if (!isalpha(*tagname)) return FALSE; for (++tagname; *tagname; ++tagname) if (!isalnum(*tagname) && *tagname != '_') return FALSE; return TRUE; } /* * "tag" is a text identifier to refer to the variable and can * be suffixed with a colon and a mob vnum ie: questobj:1101 * vnum 0 is used to denote a global tag (local to the victim) * otherwise tags are separated by vnum * * mptag <victim> <tag> [value] * mprmtag <victim> <tag> * mpflag <victim> <tag> <flag> * mprmflag <victim> <tag> <flag> * * if istagged($n,tag) [== value] * if isflagged($n,tag[,bit]) */ /* * mptag <victim> <tag> [value] */ void do_mptag( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; VARIABLE_DATA *vd; char *p; char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; int vnum = 0, exp = 0; bool error = FALSE; if ( (!IS_NPC(ch) && get_trust(ch) < LEVEL_GREATER) || IS_CHARMED(ch) ) { send_to_char( "Huh?\n\r", ch ); return; } argument = one_argument( argument, arg1 ); if ( !str_cmp(arg1, "noexpire") ) { exp = 0; argument = one_argument( argument, arg1 ); } else if ( !str_cmp(arg1, "timer") ) { argument = one_argument( argument, arg1 ); exp = atoi(arg1); argument = one_argument( argument, arg1 ); } else exp = ch->level * get_curr_int(ch); argument = one_argument( argument, arg2 ); if ( arg1[0] == '\0' || arg2[0] == '\0' ) { send_to_char( "MPtag whom with what?\n\r", ch ); return; } if ( (victim=get_char_room(ch, arg1)) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( (p=strchr(arg2, ':')) != NULL ) { *p++ = '\0'; vnum = atoi(p); } else { vnum = ch->pIndexData ? ch->pIndexData->vnum : 0; } if ( !is_valid_tag(arg2) ) { progbug( "Mptag: invalid characters in tag", ch ); return; } error = FALSE; for ( p = argument; *p; p++ ) { if ( !isdigit(*p) && !isspace(*p) ) { error = TRUE; break; } } if ( error ) { vd = make_variable(vtSTR, vnum, arg2); vd->data = str_dup(argument); } else { vd = make_variable(vtINT, vnum, arg2); (int)vd->data = atoi(argument); } vd->timer = exp; tag_char(victim, vd, 1); } /* * mprmtag <victim> <tag> */ void do_mprmtag( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; char *p; char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; int vnum = 0; if ( (!IS_NPC(ch) && get_trust(ch) < LEVEL_GREATER) || IS_CHARMED(ch) ) { send_to_char( "Huh?\n\r", ch ); return; } argument = one_argument( argument, arg1 ); argument = one_argument( argument, arg2 ); if ( arg1[0] == '\0' || arg2[0] == '\0' ) { send_to_char( "MPtag whom with what?\n\r", ch ); return; } if ( (victim=get_char_room(ch, arg1)) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( (p=strchr(arg2, ':')) != NULL ) { *p++ = '\0'; vnum = atoi(p); } else { vnum = ch->pIndexData ? ch->pIndexData->vnum : 0; } if ( !is_valid_tag( arg2 ) ) { progbug( "Mptag: invalid characters in tag", ch ); return; } if ( !remove_tag(victim, arg2, vnum) ) { progbug( "Mptag: could not find tag", ch ); } } /* * mpflag <victim> <tag> <flag> */ void do_mpflag( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; VARIABLE_DATA *vd; char *p; char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; char arg3[MAX_INPUT_LENGTH]; int vnum = 0, exp = 0, def = 0, flag = 0; bool error = FALSE; if ( (!IS_NPC(ch) && get_trust(ch) < LEVEL_GREATER) || IS_CHARMED(ch) ) { send_to_char( "Huh?\n\r", ch ); return; } argument = one_argument( argument, arg1 ); if ( !str_cmp(arg1, "noexpire") ) { exp = 0; argument = one_argument( argument, arg1 ); } else if ( !str_cmp(arg1, "timer") ) { argument = one_argument( argument, arg1 ); exp = atoi(arg1); argument = one_argument( argument, arg1 ); } else { exp = ch->level * get_curr_int(ch); def = 1; } argument = one_argument( argument, arg2 ); argument = one_argument( argument, arg3 ); if ( arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0' ) { send_to_char( "MPflag whom with what?\n\r", ch ); return; } if ( (victim=get_char_room(ch, arg1)) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( (p=strchr(arg2, ':')) != NULL ) { *p++ = '\0'; vnum = atoi(p); } else { vnum = ch->pIndexData ? ch->pIndexData->vnum : 0; } if ( !is_valid_tag(arg2) ) { progbug( "Mpflag: invalid characters in tag", ch ); return; } error = FALSE; for ( p = arg3; *p; p++ ) { if ( !isdigit(*p) && !isspace(*p) ) { error = TRUE; break; } } flag = atoi(arg3); if ( error || flag < 0 || flag >= MAX_BITS ) { progbug( "Mpflag: invalid flag value", ch ); return; } if ( (vd=get_tag(victim, arg2, vnum)) != NULL ) { if ( vd->type != vtXBIT ) { progbug( "Mpflag: type mismatch", ch ); return; } if ( !def ) vd->timer = exp; } else { vd = make_variable(vtXBIT, vnum, arg2); vd->timer = exp; } xSET_BIT(*(EXT_BV*)vd->data, flag); tag_char(victim, vd, 1); } /* * mprmflag <victim> <tag> <flag> */ void do_mprmflag( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; VARIABLE_DATA *vd; char *p; char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; char arg3[MAX_INPUT_LENGTH]; int vnum = 0; bool error = FALSE; if ( (!IS_NPC(ch) && get_trust(ch) < LEVEL_GREATER) || IS_CHARMED(ch) ) { send_to_char( "Huh?\n\r", ch ); return; } argument = one_argument( argument, arg1 ); argument = one_argument( argument, arg2 ); argument = one_argument( argument, arg3 ); if ( arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0' ) { send_to_char( "MPrmflag whom with what?\n\r", ch ); return; } if ( (victim=get_char_room(ch, arg1)) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( (p=strchr(arg2, ':')) != NULL ) { *p++ = '\0'; vnum = atoi(p); } else { vnum = ch->pIndexData ? ch->pIndexData->vnum : 0; } if ( !is_valid_tag( arg2 ) ) { progbug( "Mprmflag: invalid characters in tag", ch ); return; } error = FALSE; for ( p = arg3; *p; p++ ) { if ( !isdigit(*p) && !isspace(*p) ) { error = TRUE; break; } } if ( error ) { progbug( "Mprmflag: invalid flag value", ch ); return; } /* * Only bother doing anything if the tag exists */ if ( (vd=get_tag(victim, arg2, vnum)) != NULL ) { if ( vd->type != vtXBIT ) { progbug( "Mprmflag: type mismatch", ch ); return; } if ( !vd->data ) { progbug( "Mprmflag: missing data???", ch ); return; } xREMOVE_BIT(*(EXT_BV*)vd->data, atoi(arg3)); tag_char(victim, vd, 1); } } void fwrite_variables(CHAR_DATA *ch, FILE *fp) { VARIABLE_DATA *vd; for ( vd = ch->variables; vd; vd = vd->next ) { fprintf(fp, "#VARIABLE\n"); fprintf(fp, "Type %d\n", vd->type); fprintf(fp, "Flags %d\n", vd->flags); fprintf(fp, "Vnum %d\n", vd->vnum); fprintf(fp, "Ctime %ld\n", vd->c_time); fprintf(fp, "Mtime %ld\n", vd->m_time); fprintf(fp, "Rtime %ld\n", vd->r_time); fprintf(fp, "Timer %d\n", vd->timer); fprintf(fp, "Tag %s~\n", vd->tag); switch(vd->type) { case vtSTR: fprintf(fp, "Str %s~\n", (char *)vd->data); break; case vtXBIT: fprintf(fp, "Xbit %s\n", print_bitvector((EXT_BV*)vd->data)); break; case vtINT: fprintf(fp, "Int %d\n", (int)vd->data); break; } fprintf(fp, "End\n\n"); } } void fread_variable(CHAR_DATA *ch, FILE *fp) { VARIABLE_DATA *pvd; char *word; bool fMatch; CREATE(pvd, VARIABLE_DATA, 1); for ( ; ; ) { word = feof( fp ) ? "End" : fread_word( fp ); fMatch = FALSE; switch ( UPPER(word[0]) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case 'C': KEY( "Ctime", pvd->c_time, fread_number( fp ) ); break; case 'E': if ( !str_cmp( word, "End" ) ) { switch(pvd->type) { default: { bug("Fread_variable: invalid/incomplete variable %s", pvd->tag); if ( pvd->tag ) DISPOSE(pvd->tag); DISPOSE(pvd); break; } case vtSTR: case vtXBIT: if ( !pvd->data ) { bug("Fread_variable: invalid/incomplete variable %s", pvd->tag); if ( pvd->tag ) DISPOSE(pvd->tag); DISPOSE(pvd); break; } case vtINT: tag_char(ch, pvd, 1); break; } return; } break; case 'F': KEY( "Flags", pvd->flags, fread_number( fp ) ); break; case 'I': if ( !str_cmp(word, "Int") ) { if ( pvd->type != vtINT ) bug("Fread_variable: Type mismatch -- type(%d) != vtInt", pvd->type); else { (int)pvd->data = fread_number(fp); fMatch = TRUE; } break; } break; case 'M': KEY( "Mtime", pvd->m_time, fread_number( fp ) ); break; case 'R': KEY( "Rtime", pvd->r_time, fread_number( fp ) ); break; case 'S': if ( !str_cmp(word, "Str") ) { if ( pvd->type != vtSTR ) bug("Fread_variable: Type mismatch -- type(%d) != vtSTR", pvd->type); else { (char *)pvd->data = fread_string_nohash(fp); fMatch = TRUE; } break; } break; case 'T': KEY( "Tag", pvd->tag, fread_string_nohash( fp ) ); KEY( "Timer", pvd->timer, fread_number( fp ) ); KEY( "Type", pvd->type, fread_number( fp ) ); break; case 'V': KEY( "Vnum", pvd->vnum, fread_number( fp ) ); break; case 'X': if ( !str_cmp(word, "Xbit") ) { if ( pvd->type != vtXBIT ) bug("Fread_variable: Type mismatch -- type(%d) != vtXBIT", pvd->type); else { CREATE(pvd->data, EXT_BV, 1); *(EXT_BV *)pvd->data = fread_bitvector(fp); fMatch = TRUE; } break; } break; } if ( !fMatch ) { bug( "Fread_variable: no match: %s", word ); } } }