/**************************************************************************** * [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 <stdio.h> #include <string.h> #include <ctype.h> #include "h/mud.h" #include "h/key.h" 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 = STRALLOC(tag); var->c_time = current_time; var->m_time = current_time; var->r_time = 0; var->timer = 0; switch (type) { case vtINT: case vtSTR: var->data = NULL; break; case vtXBIT: CREATE(var->data, EXT_BV, 1); break; } return var; } void delete_vdata(VARIABLE_DATA * var) { char *strdata; switch (var->type) { case vtXBIT: if(var->data) DISPOSE(var->data); break; case vtSTR: if(var->data) { strdata = (char *)var->data; STRFREE(strdata); var->data = NULL; } break; } } void delete_variable(VARIABLE_DATA * var) { delete_vdata(var); STRFREE(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(!str_cmp(tag, vd->tag)) // 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_AJ_SGT) || IS_AFFECTED(ch, AFF_CHARM)) { send_to_char("Huh?\r\n", 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?\r\n", ch); return; } if((victim = get_char_room(ch, arg1)) == NULL) { send_to_char("They aren't here.\r\n", 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(ch, "Mptag: invalid characters in tag"); return; } error = FALSE; const char *p2; for(p2 = argument; *p2; p2++) { if(!isdigit(*p2) && !isspace(*p2)) { error = TRUE; break; } } if(error) { vd = make_variable(vtSTR, vnum, arg2); vd->data = STRALLOC(argument); } else { vd = make_variable(vtINT, vnum, arg2); vd->data = (void *)(atol(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_AJ_SGT) || IS_AFFECTED(ch, AFF_CHARM)) { send_to_char("Huh?\r\n", 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?\r\n", ch); return; } if((victim = get_char_room(ch, arg1)) == NULL) { send_to_char("They aren't here.\r\n", 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(ch, "Mptag: invalid characters in tag"); return; } if(!remove_tag(victim, arg2, vnum)) { progbug(ch, "Mptag: could not find tag"); } } /* * 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_AJ_SGT) || IS_AFFECTED(ch, AFF_CHARM)) { send_to_char("Huh?\r\n", 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?\r\n", ch); return; } if((victim = get_char_room(ch, arg1)) == NULL) { send_to_char("They aren't here.\r\n", 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(ch, "Mpflag: invalid characters in tag"); 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(ch, "Mpflag: invalid flag value"); return; } if((vd = get_tag(victim, arg2, vnum)) != NULL) { if(vd->type != vtXBIT) { progbug(ch, "Mpflag: type mismatch"); 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_AJ_SGT) || IS_AFFECTED(ch, AFF_CHARM)) { send_to_char("Huh?\r\n", 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?\r\n", ch); return; } if((victim = get_char_room(ch, arg1)) == NULL) { send_to_char("They aren't here.\r\n", 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(ch, "Mprmflag: invalid characters in tag"); return; } error = FALSE; for(p = arg3; *p; p++) { if(!isdigit(*p) && !isspace(*p)) { error = TRUE; break; } } if(error) { progbug(ch, "Mprmflag: invalid flag value"); return; } /* * Only bother doing anything if the tag exists */ if((vd = get_tag(victim, arg2, vnum)) != NULL) { if(vd->type != vtXBIT) { progbug(ch, "Mprmflag: type mismatch"); return; } if(!vd->data) { progbug(ch, "Mprmflag: missing data???"); 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 %ld\n", (long)vd->data); break; } fprintf(fp, "End\n\n"); } } void fread_variable(CHAR_DATA *ch, FILE * fp) { VARIABLE_DATA *pvd; const 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("%s: invalid/incomplete variable: %s", __FUNCTION__, pvd->tag); STRFREE(pvd->tag); DISPOSE(pvd); break; } case vtSTR: case vtXBIT: if(!pvd->data) { bug("%s: invalid/incomplete variable: %s", __FUNCTION__, pvd->tag); STRFREE(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("%s: Type mismatch -- type(%d) != vtInt", __FUNCTION__, pvd->type); else { pvd->data = (void *)((long)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("%s: Type mismatch -- type(%d) != vtSTR", __FUNCTION__, pvd->type); else { pvd->data = fread_string(fp); fMatch = TRUE; } break; } break; case 'T': KEY("Tag", pvd->tag, fread_string(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("%s: Type mismatch -- type(%d) != vtXBIT", __FUNCTION__, pvd->type); else { CREATE(pvd->data, EXT_BV, 1); *(EXT_BV *) pvd->data = fread_bitvector(fp); fMatch = TRUE; } break; } break; } if(!fMatch) bug("%s: no match: %s", __FUNCTION__, word); } }