/* ************************************************************************ * File: quest.c A utility to CircleMUD * * Usage: writing/reading player's quest bits * * * * Code done by Billy H. Chan * * * ************************************************************************ */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "structs.h" #include "utils.h" #include "interpreter.h" void send_to_char(char *messg, struct char_data *ch); struct char_data *get_char_vis(struct char_data *ch, char *arg1); void free_quest(struct quest * q) { free(q); } void write_quests(struct char_data *ch) { FILE *file; char fn[127]; struct quest *temp; get_filename(GET_NAME(ch),fn,QUEST_FILE); unlink(fn); if( !GET_QUESTS(ch) ) return; file = fopen(fn,"wt"); temp = GET_QUESTS(ch); while( temp ) { fwrite(temp, sizeof(struct quest), 1, file); temp = temp->next; } fclose(file); } void read_quests(struct char_data *ch) { FILE *file; char fn[127]; struct quest *temp, *temp2; get_filename(GET_NAME(ch),fn,QUEST_FILE); file = fopen(fn,"r"); if( !file ) return; CREATE(GET_QUESTS(ch),struct quest,1); temp = GET_QUESTS(ch); do { fread(temp, sizeof(struct quest), 1, file); if( !feof(file) ){ CREATE(temp2,struct quest,1); temp->next = temp2; temp = temp->next; } } while( !feof(file) ); fclose(file); } struct quest *find_quest(struct char_data * ch, int zone) { struct quest * previous, *temp, * next = GET_QUESTS(ch); bool contloop = TRUE; previous = NULL; while ((next != NULL) && contloop) { if (next->zone < zone) { previous = next; next = next->next; } else if (next->zone == zone) return next; else contloop = FALSE; } CREATE(temp, struct quest, 1); temp->zone = zone; temp->firstrow = 0; temp->secondrow = 0; temp->next = next; if (previous) previous->next = temp; else GET_QUESTS(ch) = temp; return temp; } questrow get_quest_bits(struct char_data * ch, int zone, int row, int offset, int length) { struct quest * q; questrow temp, accum = 0; int i = 0; q = find_quest(ch, zone); if (row >= 2) temp = q->secondrow; else temp = q->firstrow; while (i < length) { if (IS_SET(temp, 1 << (offset + i))) SET_BIT(accum, 1 << i); i++; } return accum; } void change_quest_bits(struct char_data * ch, int zone, int row, int offset, int length, int value) { struct quest * q; questrow loc; int i = 0; if (offset < 0) offset = 0; if (offset > 31) offset = 31; while ((offset + length) > 32) { length--; } q = find_quest(ch, zone); if (row >= 2) loc = q->secondrow; else loc = q->firstrow; while (i < length) { if (IS_SET(value, 1 << i)) SET_BIT(loc, 1 << (offset + i)); else REMOVE_BIT(loc, 1 << (offset + i)); i++; } if (row >= 2) q->secondrow = loc; else q->firstrow = loc; } void add_quest_bits(struct char_data * ch, int zone, int row, int offset, int length, int value) { struct quest * q; questrow loc; if (offset < 0) offset = 0; if (offset > 31) offset = 31; while ((offset + length) >= 32) length --; q = find_quest(ch, zone); if (row >= 2) loc = q->secondrow; else loc = q->firstrow; if (value >= (1 << (length + 1))) value -= (1 << (length + 1)); loc += (value << offset); if (row >= 2) q->secondrow = loc; else q->firstrow = loc; } ACMD(do_showquest) { int zone, i, j; struct char_data * victim; questrow temp; char buf[256], arg1[256], arg2[256]; if (!*argument) { strcpy(buf, "Showquest usage: showquest <player> <zone>\r\n"); send_to_char(buf, ch); return; } strcpy(buf, two_arguments(argument, arg1, arg2)); if (!*arg2) { strcpy(buf, "Showquest usage: showquest <player> <zone>\r\n"); send_to_char(buf, ch); return; } victim = get_char_vis(ch, arg1); zone = atoi(arg2); sprintf(buf, "%-35.35s01234567890123456789012345678901\r\n", GET_NAME(victim)); send_to_char(buf, ch); for (j = 1; j <= 2; j++) { temp = get_quest_bits(victim, zone, j, 0, 32); sprintf(buf, "Questbits for Zone %d in Row %d is: ", zone, j); sprintf(buf, "%-35.35s", buf); for (i = 0; i < 32; i++) { if (temp & 1) sprintf(buf, "%s1", buf); else sprintf(buf, "%s0", buf); temp = temp >> 1; } strcat(buf, "\r\n"); send_to_char(buf, ch); } } ACMD(do_setquest) { int zone, offset, length, row; long value; struct char_data * victim; questrow temp; char buf[256], arg1[256]; if (!*argument) { if (subcmd == SCMD_SET_QUEST_BIT) strcpy(buf, "setquest usage: setquest <player> <zone> <row> <offset> <length> <value>\r\n"); else strcpy(buf, "addquest usage: addquest <player> <zone> <row> <offset> <length> <value>\r\n"); send_to_char(buf, ch); return; } half_chop(argument, arg1, argument); victim = get_char_vis(ch, arg1); half_chop(argument, arg1, argument); zone = atoi(arg1); if (!*arg1 || (zone < 0) || (zone > 500)) { strcpy(buf, "zone must be a number between 0 and 500"); send_to_char(buf, ch); return; } half_chop(argument, arg1, argument); row = atoi(arg1); if (!*arg1 || (row < 0) || (row > 2)) { strcpy(buf, "row must be a number between 1 and 2"); send_to_char(buf, ch); return; } half_chop(argument, arg1, argument); offset = atoi(arg1); if (!*arg1 || (offset < 0) || (offset > 31)) { strcpy(buf, "offset must be a number between 0 and 31"); send_to_char(buf, ch); return; } half_chop(argument, arg1, argument); length = atoi(arg1); if (!*arg1 || (length < 0) || (length > 32)) { strcpy(buf, "length must be a number between 1 and 32"); send_to_char(buf, ch); return; } if (length + offset > 32) { strcpy(buf, "length and offset must not exceed 32"); send_to_char(buf, ch); return; } half_chop(argument, arg1, argument); if (!*arg1) { strcpy(buf, "a value must be given"); send_to_char(buf, ch); return; } value = atol(arg1); if (subcmd != SCMD_SET_QUEST_BIT) { temp = get_quest_bits(victim, zone, row, offset, length); if (value >= 0) value += temp; else value = temp & ~value; } change_quest_bits(victim, zone, row, offset, length, value); send_to_char("Quest bit has been modified.\r\n", ch); }