/*------------------------------------------------------------------------------ This snippet is a simple addition to the goto, at, and transfer commands, which enables you to create and maintain a list of symbolic location names. For instance, on End of Time (the MUD for which I originally wrote this), you could type 'goto termina' to reach a room on the world map just south of Termina. -------------------------------------------------------------------------------- Add this to your other structure typedefs in merc.h... typedef struct location_data LOCATION; Add this wherever you'd like in merc.h... struct location_data { bool valid; LOCATION * next; char * name; long vnum; int level; }; Add this with your other function prototypes in merc.h... ROOM_INDEX_DATA * location_lookup (CHAR_DATA * ch, char * argument); LOCATION * new_loc (void); void free_loc (LOCATION * loc); void save_locations (void); void load_locations (void); Add this to merc.h along with similar things, such as char_list... extern LOCATION * location_list; Add this to interp.h, and add the corresponding command entry to interp.c. To get decent use out of it, I recommend making it LEVEL_IMMORTAL. DECLARE_DO_FUN( do_locations ); Now, in act_wiz.c, add this to the top of find_location(): ROOM_INDEX_DATA * pRoom; In the same function, add this, below the is_number check: if ((pRoom = location_lookup (ch, arg)) != NULL) return pRoom; Add this to db.c, with load_bans() and such: load_locations (); Now, add the rest of this file (location.c) to your src directory, and if needed, to your makefile. Do a clean compile, and you should be good to go. To generate a locations.txt file, just make a location and use the save option. --------------------------------------------------------------------Cut Here--*/ /*************************************************************************** * This code may be used freely within any non-commercial MUD, all I ask * * is that these comments remain in tact and that you give me any feedback * * or bug reports you come up with. * * -- Midboss (eclipsing.souls@gmail.com) * ***************************************************************************/ #if defined(macintosh) #include <types.h> #else #include <sys/types.h> #include <sys/time.h> #endif #include <stdio.h> #include <string.h> #include <stdlib.h> #include "merc.h" LOCATION * location_list; /* * Syntax: location * Syntax: location add <name> <vnum> * Syntax: location delete <name> [level] * Syntax: location save */ void do_locations (CHAR_DATA * ch, char * argument) { char arg[MIL], arg2[MIL], arg3[MIL]; LOCATION * pLoc; argument = one_argument (argument, arg); argument = one_argument (argument, arg2); argument = one_argument (argument, arg3); //Are we looking for a list? if (arg[0] == '\0' || !str_prefix (arg, "list")) { bool found = FALSE; char buf[MSL]; //Initialize the buffer... buf[0] = '\0'; //Header. sprintf (buf + strlen (buf), "{DYou may goto the following pre-defined points:{x\n\r"); //Let's build a list. for (pLoc = location_list; pLoc != NULL; pLoc = pLoc->next) { //We can use this one, right? if (pLoc->level > get_trust (ch)) continue; //Set it to true. if (!found) found = TRUE; //Add it to the buffer. sprintf (buf + strlen (buf), "{W%-20s {r[{Droom %ld{r, {Dlevel %d{r]{x\n\r", pLoc->name, pLoc->vnum, pLoc->level); } //None found? if (!found) send_to_char ( "{DYou may not use any pre-defined goto points.{x\n\r", ch); //Send the buffer. else send_to_char (buf, ch); return; } else if (!str_prefix (arg, "save")) save_locations (); //Creating one? else if (!str_prefix (arg, "add") || !str_prefix (arg, "create")) { ROOM_INDEX_DATA * pRoom; long vnum; int level; //Not just anyone can do this. if (get_trust (ch) < SUPREME) { send_to_char ("{DYou're not authorized to do that.{x\n\r", ch); return; } //We have a name, right? if (arg2[0] == '\0') { send_to_char ("{DYou need to provide a name.{x\n\r", ch); return; } //Idiot-proofing. if (strlen (arg2) > 20 || strlen (arg2) < 3) { send_to_char ( "{DThat name is either too long or too short.{x\n\r", ch); return; } //Make sure we have a vnum. if (arg3[0] == '\0' || !is_number (arg3)) { send_to_char ("{DYou need to provide a room vnum.{x\n\r", ch); return; } //Find out if the room exists. vnum = atoi (arg3); if ((pRoom = get_room_index (vnum)) == NULL) { send_to_char ("{DThat room doesn't exist.{x\n\r", ch); return; } //Optional level setting. if (argument[0] == '\0') level = LEVEL_IMMORTAL; else { //Not a number? if (!is_number (argument)) { send_to_char ("{DLevels must be numerical.{x\n\r", ch); return; } //Make sure it's a legal level. level = atoi (argument); if (level > get_trust (ch) || level < LEVEL_IMMORTAL) { send_to_char ("{DYou can't do that.{x\n\r", ch); return; } } //Create the location and stick it in the list. pLoc = new_loc (); free_string (pLoc->name); pLoc->name = str_dup (arg2); pLoc->vnum = vnum; pLoc->level = level; pLoc->next = location_list; location_list = pLoc; return; } else if (!str_prefix (arg, "delete")) { LOCATION * list; LOCATION * prev; //Can we do it? if (get_trust (ch) < SUPREME) { send_to_char ("{DYou're not authorized to do that.{x\n\r", ch); return; } //No arg? if (arg2[0] == '\0') { send_to_char ("{DWhich goto point do you want to delete?{x\n\r", ch); return; } //Make sure it's NULL, then try to find one. pLoc = NULL; for (list = location_list; list != NULL; list = list->next) { if (list->level > get_trust (ch)) continue; if (!str_prefix (arg2, list->name)) { pLoc = list; break; } } //No location? if (pLoc == NULL) { send_to_char ("{DNo such goto point.{x\n\r", ch); return; } //Now remove it. if (pLoc == location_list) { location_list = pLoc->next; free_loc (pLoc); } else { for (prev = location_list; prev != NULL; prev = prev->next) { if (prev->next == pLoc) { prev->next = pLoc->next; free_loc (pLoc); } } } //Done. send_to_char ("{DGoto point deleted.{x\n\r", ch); return; } //Get a list. else do_locations (ch, ""); } /* * Look up a 'goto point' room. */ ROOM_INDEX_DATA * location_lookup (CHAR_DATA * ch, char * argument) { ROOM_INDEX_DATA * pRoom; LOCATION * list; for (list = location_list; list != NULL; list = list->next) { if (list->level > get_trust (ch)) continue; if (!str_prefix (argument, list->name) && (pRoom = get_room_index (list->vnum)) != NULL) return pRoom; } return NULL; } //Save all locations. void save_locations (void) { LOCATION * pLoc; FILE * fp; if ((fp = fopen ("locations.txt", "w")) == NULL) { bug ("Location list not found.", 0); return; } for (pLoc = location_list; pLoc != NULL; pLoc = pLoc->next) fprintf (fp, "Loc %s~ %ld %d\n", pLoc->name, pLoc->vnum, pLoc->level); fprintf (fp, "End\n"); fclose (fp); return; } //Load all locations. void load_locations (void) { LOCATION * pLoc; FILE * fp; char * word; bool fMatch; //Get the file. if ((fp = fopen ("locations.txt", "r")) == NULL) { bug ("Location list not found.", 0); return; } for (;;) { word = feof (fp) ? "End" : fread_word (fp); fMatch = FALSE; switch (UPPER(word[0])) { //Comment. case '*': fMatch = TRUE; fread_to_eol (fp); break; //Load a location... case 'L': if (!str_cmp (word, "Loc")) { pLoc = new_loc (); free_string (pLoc->name); pLoc->name = fread_string (fp); pLoc->vnum = fread_number (fp); pLoc->level = fread_number (fp); pLoc->next = location_list; location_list = pLoc; fMatch = TRUE; break; } break; //End of list? case 'E': if (!str_cmp (word, "End")) return; break; } } fclose (fp); } /* * Recycling stuff. */ LOCATION * loc_free; LOCATION * new_loc (void) { static LOCATION loc_zero; LOCATION *loc; if (loc_free == NULL) loc = alloc_perm (sizeof (*loc)); else { loc = loc_free; loc_free = loc_free->next; } *loc = loc_zero; VALIDATE (loc); loc->name = &str_empty[0]; return loc; } void free_loc (LOCATION * loc) { if (!IS_VALID (loc)) return; free_string (loc->name); INVALIDATE (loc); loc->next = loc_free; loc_free = loc; }