/**************************************************************************** * [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. * * ------------------------------------------------------------------------ * * Online Hints module by Zedd of Slips in Time * ****************************************************************************/ #include <stdio.h> #include <ctype.h> #include "h/mud.h" #include "h/files.h" #include "h/hint.h" #include "h/key.h" HINT_DATA *first_hint; HINT_DATA *last_hint; void free_hint(HINT_DATA * hint) { if(!hint) return; UNLINK(hint, first_hint, last_hint, next, prev); STRFREE(hint->text); DISPOSE(hint); } void free_hints(void) { HINT_DATA *hint, *hint_next; for(hint = first_hint; hint; hint = hint_next) { hint_next = hint->next; free_hint(hint); } } void SwapHint(HINT_DATA * pHint1, HINT_DATA * pHint2) { if(pHint1->prev) pHint1->prev->next = pHint2; else first_hint = pHint2; pHint2->prev = pHint1->prev; pHint1->next = pHint2->next; if(pHint1->next) pHint1->next->prev = pHint1; pHint2->next = pHint1; pHint1->prev = pHint2; } char *get_hint(int level) { HINT_DATA *hintData; bool found = FALSE; static char buf[MAX_STRING_LENGTH]; int count, which; count = 0; if(level < 0) { snprintf(buf, MAX_STRING_LENGTH, "HintLevel error, Level was %d", level); return buf; } else { found = FALSE; hintData = first_hint; for(hintData = first_hint; hintData; hintData = hintData->next) { if(level >= hintData->low && level <= hintData->high) ++count; } if(count > 1) { which = number_range(1, count); count = 0; for(hintData = first_hint; hintData; hintData = hintData->next) { if(level >= hintData->low && level <= hintData->high) ++count; if(count == which) { mudstrlcpy(buf, hintData->text, MAX_STRING_LENGTH); return buf; } } } else if(count == 1) { for(hintData = first_hint; hintData; hintData = hintData->next) { if(level >= hintData->low && level <= hintData->high) { mudstrlcpy(buf, hintData->text, MAX_STRING_LENGTH); return buf; } } } else return (char *)" "; } return (char *)" "; } void write_hint(void) { HINT_DATA *hintData; FILE *fp; char filename[256]; sprintf(filename, "%s", HINT_FILE); if((fp = FileOpen(filename, "w")) == NULL) { bug("write_hint: FileOpen"); perror(filename); return; } else { for(hintData = first_hint; hintData; hintData = hintData->next) { fprintf(fp, "Text %s~\n", hintData->text); fprintf(fp, "Low %d\n", hintData->low); fprintf(fp, "High %d\n", hintData->high); fprintf(fp, "%s", "End\n"); } FileClose(fp); fp = NULL; return; } } void do_hintedit(CHAR_DATA *ch, char *argument) { char arg[MAX_STRING_LENGTH]; char arg2[MAX_STRING_LENGTH]; char arg3[MAX_STRING_LENGTH]; HINT_DATA *hintData; int i; int no = 0; int ano = 0; bool found = FALSE; if(IS_NPC(ch)) return; if(!IS_IMMORTAL(ch)) return; set_char_color(AT_LBLUE, ch); argument = one_argument(argument, arg); argument = one_argument(argument, arg2); argument = one_argument(argument, arg3); if(!str_cmp(arg, "help") || arg[0] == '\0') { do_help(ch, (char *)"sethint"); return; } if(!str_cmp(arg, "list")) { if(first_hint) { pager_printf(ch, "No | Low | High | Text \r\n"); pager_printf(ch, "---|-----|------|--------------------------------------------------\r\n"); i = 0; for(hintData = first_hint; hintData; hintData = hintData->next) { ++i; pager_printf(ch, "%2d | %3d | %4d | %s\r\n", i, hintData->low, hintData->high, hintData->text); } pager_printf(ch, "\r\n%d hints in file.\r\n", i); } else send_to_char("No hints in file.\r\n", ch); return; } else if(!str_cmp(arg, "remove")) { no = 0; if(!is_number(arg2)) { send_to_char_color("Remove which hint?\r\n", ch); return; } ano = atoi(arg2); found = FALSE; for(hintData = first_hint; hintData; hintData = hintData->next) { ++no; if(no == ano) { ch_printf_color(ch, "&CHint Number %d removed\r\n", ano); UNLINK(hintData, first_hint, last_hint, next, prev); STRFREE(hintData->text); DISPOSE(hintData); found = TRUE; break; } } if(!found) { send_to_char("Hint not found\r\n", ch); return; } return; } else if(!str_cmp(arg, "add")) { if(*arg2 == '\0') { send_to_char("What is the minimum level for this hint?\r\n", ch); return; } if(*arg3 == '\0') { send_to_char("What is the maximum level for this hint?\r\n", ch); return; } if(atoi(arg2) > atoi(arg3)) { send_to_char("Aborting: max less than min!\r\n", ch); return; } CREATE(hintData, HINT_DATA, 1); hintData->low = atoi(arg2); hintData->high = atoi(arg3); hintData->text = STRALLOC(argument); LINK(hintData, first_hint, last_hint, next, prev); send_to_char("Ok. Hint created\r\n", ch); return; } else if(!str_cmp(arg, "force")) { /* Volk or Taon change this to force players to see a certain hint # */ ch_printf_color(ch, "\r\n&Chint: &c%s\r\n", get_hint(LEVEL_AVATAR)); return; } else if(!str_cmp(arg, "edit")) { no = 0; i = 0; if(arg2[0] == '\0') { send_to_char("Edit which hint number?\r\n", ch); return; } else no = atoi(arg2); if(arg3[0] == '\0') { ch_printf(ch, "Edit which field of hint %d (low/high/text)?\r\n", no); return; } if(argument[0] == '\0') { ch_printf(ch, "Change hint %d's field %s to what ?\r\n", no, arg3); return; } for(hintData = first_hint; hintData; hintData = hintData->next) { ++i; if(i == no) { found = TRUE; break; } } if(!found) { ch_printf(ch, "Hint %d not found.\r\n", no); return; } else { if(!str_cmp(arg3, "text")) { STRFREE(hintData->text); hintData->text = STRALLOC(argument); send_to_char("Hint text changed!\r\n", ch); return; } else if(!str_cmp(arg3, "low")) { if(atoi(argument) > hintData->high) { send_to_char("Aborting: min higher than max.\r\n", ch); return; } hintData->low = atoi(argument); send_to_char("Minimum level for hint changed.\r\n", ch); return; } else if(!str_cmp(arg3, "high")) { if(atoi(argument) < hintData->low) { send_to_char("Aborting: max lower than min.\r\n", ch); return; } hintData->high = atoi(argument); send_to_char("Maximum level for hint changed.\r\n", ch); return; } else { send_to_char("Valid fields are: low/high/text\r\n", ch); return; } } } else if(!str_cmp(arg, "save")) { write_hint(); send_to_char("Saved.\r\n", ch); return; } else { send_to_char("Syntax: sethint (list/add/remove/edit/save/force)\r\n", ch); return; } } HINT_DATA *read_hint(char *filename, FILE * fp) { HINT_DATA *hintData; const char *word; bool fMatch; char letter; do { letter = getc(fp); if(feof(fp)) { FileClose(fp); fp = NULL; return NULL; } } while(isspace(letter)); ungetc(letter, fp); CREATE(hintData, HINT_DATA, 1); hintData->next = NULL; hintData->prev = NULL; hintData->text = STRALLOC(""); hintData->low = 0; hintData->high = 0; for(;;) { word = feof(fp) ? "End" : fread_word(fp); fMatch = FALSE; switch (UPPER(word[0])) { case 'T': if(!str_cmp(word, "Text")) STRFREE(hintData->text); KEY("Text", hintData->text, fread_string(fp)); break; case 'E': if(!str_cmp(word, "End")) { if(!hintData->text) hintData->text = STRALLOC(""); return hintData; } break; case 'H': KEY("High", hintData->high, fread_number(fp)); break; case 'L': KEY("Low", hintData->low, fread_number(fp)); break; } if(!fMatch) bug("read_hint: no match: %s", word); } STRFREE(hintData->text); DISPOSE(hintData); return NULL; } void load_hint(void) { char filename[256]; FILE *fp; HINT_DATA *hintData; first_hint = last_hint = NULL; snprintf(filename, 256, "%s", HINT_FILE); if((fp = FileOpen(filename, "r")) == NULL) return; while((hintData = read_hint(filename, fp)) != NULL) LINK(hintData, first_hint, last_hint, next, prev); return; }