/*********************************************************** Realms of Aurealis Online Creation System version 2.1 RoAOLCv2.1 - James Rhone aka Vall of RoA roaolc.c (online creation system - mob/room/object/house edit files) Adopted from Realms of Imagination's original version of OLC (7/95) ******** Heavily modified and expanded ******** *** BE AWARE OF ALL RIGHTS AND RESERVATIONS *** ******** Heavily modified and expanded ******** All rights reserved henceforth. Author: James Rhone Original Running Version: 0.5beta Please note that no guarantees are associated with any code from Realms of Aurealis. All code which has been released to the general public has been done so with an 'as is' pretense. Thanks to Jeremy Elson who has provided a stable base for Realms of Aurealis. RoA was originally created from a CircleMUD 2.2 base, back in the dark ages, when even that release was considered new wave. Since RoA is a perpetual BETA MUD, all code from it is also in BETA stages. I personally feel this is the best OLC ever made available for CircleMUD and its derivatives. My experienced builders agree. How you feel depends on how well you can fit into your mud. Good luck. There are no patch files, no step by step instructions, and no hand holders. All code written for Realms of Aurealis, including that contained in this file was written by me, James Rhone, so nobody is very familiar with it except me. Perhaps that will change. :) *** If you do not know C, I suggest getting to know it before you attempt to plug this into your mud. This is not a trivial addition to any mud and without someone there to guide you, you will inevitably get frustrated. ** note: zone OLC can be found in z_olc.c note: room OLC can be found in r_olc.c note: mobile OLC can be found in m_olc.c note: object OLC can be found in o_olc.c **********************************************************/ #include "conf.h" #include "sysdep.h" #include "structures.h" #include "comm.h" #include "interpreter.h" #include "acmd.h" #include "db.h" #include "utils.h" #include "mudlimits.h" #include "handler.h" #include "roaolc.h" #include "magic.h" #include "house.h" #include "lists.h" #include "global.h" #include "clicomm.h" // external functions and variables extern char *dirs[]; extern char *room_bits[]; extern exdescdata *correct_extra_descrips(exdescdata *ths); // no more duping this bit of code... BOOL olc_perms(chdata *ch, int level_override, int zone) { if (GET_LEVEL(ch) < level_override && (zone == 0 || zone < ch->pc_specials->saved.olc_min_zone || zone > ch->pc_specials->saved.olc_max_zone)) { send_to_char("RoAOLC: Insufficient permissions.\n\r",ch); return FALSE; } else return TRUE; } // send version and menu title to char in RoAOLC void menu_title_send(char *menu, chdata *ch) { char buf[MAX_STRING_LENGTH]; if (PLR_FLAGGED(ch, PLR_REFRESH)) clrscr(ch); sprintf(buf, "\n\r %%B%%5%s %s%%0\n\r", OLC_version, menu); S2C(); } // assigning / revocation of building privs ACMD(do_olc) { char buf[MAX_STRING_LENGTH]; char func[MAX_STRING_LENGTH]; chdata *person; int min_zone, max_zone; if (IS_NPC(ch)) return; if (*argument) { argument = one_argument(argument, buf); person = get_char_vis(ch, buf); } else person = ch; if (!person) { send_to_char("No such person is around.\n\r", ch); return; } if (IS_NPC(person)) { send_to_char("NPC's don't have OLC privileges.\n\r", ch); return; } if (!IS_IMMORTAL(person)) { send_to_char("Must be immortal.\n\r",ch); return; } if (GET_LEVEL(person) > GET_LEVEL(ch)) { send_to_char("Pick on someone your own size.\n\r", ch); return; } if (*argument && GET_LEVEL(ch) >= LEV_AIMP) { argument = one_argument(argument, func); if (!*argument || !strlen(func)) { send_to_char("usage: OLC <player> all <min zone> [<max zone>]\n\r", ch); return; } argument = one_argument(argument, buf); min_zone = atoi(buf); if (!*argument) max_zone = min_zone; else { argument = one_argument(argument, buf); max_zone = atoi(buf); } if (max_zone < min_zone) { send_to_char("The maximum zone must be greater or " "equal to the minimum zone.\n\r", ch); return; } person->pc_specials->saved.olc_min_zone = min_zone; person->pc_specials->saved.olc_max_zone = max_zone; } act("RoAOLC privs for $N:", FALSE,ch,0,person,TO_CHAR); sprintf(buf, "Zones: %3d - %3d\n\r", person->pc_specials->saved.olc_min_zone, person->pc_specials->saved.olc_max_zone); S2C(); } // list rooms/chars in a particular zone ACMD(do_zlist) { rmdata *w; chdata *x; int zone; int i, top; char buf[20000]; if (IS_NPC(ch)) return; one_argument(argument, buf); if (!*buf || *buf == '.') zone = world[ch->in_room].zone; else zone = real_zone(atoi(buf)); if (zone < 0) { send_to_char("That zone does not exist.\n\r",ch); return; } if (!olc_perms(ch, LEV_GOD, zone)) return; if (ZONE_FREED(zone)) { send_to_char("The rooms from that zone are not stored in memory.\n\r",ch); send_to_char("Use %Bzlock%0 to load them into memory.\n\r",ch); return; } top = zone_table[zone].top; for (i = zone * 100; i <= top; i++) { if (real_room(i) >= 0) break; } if (i > top) return; buf[0] = '\0'; while (i <= top) { if (real_room(i) < 0) { i++; continue; } w = &world[real_room(i)]; sprintf(buf1, "[%%B%%6%5d%%0]\t%-22.22s%%0\t", i, w->name); sprintbit(w->room_flags, room_bits, buf2); strcat(buf1, buf2); strcat(buf1, "\n\r"); x = w->people; while (x) { if (IS_NPC(x)) sprintf(buf2, "\t[%%B%2d NPC%%0] %s\n\r", GET_LEVEL(x), x->player.name); else sprintf(buf2, "\t[%%5%2d %s%%0] %s\n\r", GET_LEVEL(x), CLASS_ABBR(x), x->player.name); strcat(buf1, buf2); strcat(buf, buf1); *buf1 = '\0'; x = x->next_in_room; } i++; } page_string(ch->desc, buf, 1); } /* simply toggles clrscreen flag for builders */ ACMD(do_refresh) { if (IS_NPC(ch)) return; if (!PLR_FLAGGED(ch, PLR_REFRESH)) { SET_BIT(PLR_FLAGS(ch), PLR_REFRESH); send_to_char("%5OLC refresh %Bon%0.\n\r",ch); return; } REMOVE_BIT(PLR_FLAGS(ch), PLR_REFRESH); send_to_char("%5OLC refresh %Boff%0.\n\r",ch); } // throw a string into a file -roa void string_to_file(char *text, char *fname) { FILE *fp; char buffer[85000]; strcpy(buffer, text); killr(buffer); if (!(fp = fopen(fname, "wt"))) { sprintf(buf, "SYSERR: Could not open %s.", fname); return; } fprintf(fp, "%s", buffer); fclose(fp); } // dont push onto the stack, just jump char to this menu int menu_jump(chdata *ch, void (*to_menu)(chdata *ch, char *input_str)) { MENU_HANDLER(ch) = to_menu; (*MENU_HANDLER(ch))(ch, NULL); return 1; } // throw current onto stack, then jump int menu_push_jump(chdata *ch, void (*to_menu)(chdata *ch, char *input_str)) { menu_push(ch); MENU_HANDLER(ch) = to_menu; (*MENU_HANDLER(ch))(ch, NULL); return 1; } // OK, i'll attempt to spawn off a diff editor, after they are done // ill put the file they editted into d->str // then call string_add int do_max_string_arg(chdata *ch, char *prompt, char **return_ptr) { char shellfname[100]; char fname[100]; BOOL cliedit = FALSE; extern void startshell(dsdata *d, char *x, char *y); menu_push(ch); // RoA // OK, if using alternate editor for these large files // write the current *return_ptr to their edit file so // spico can read it if (PLR_FLAGGED(ch, PLR_EXEDIT)) { sprintf(fname, "edits/%s.edit", GET_NAME(ch)); // delete the file if it exists if (unlink(fname) < 0) { if (errno != ENOENT) { /* if it fails, NOT because of no file */ sprintf(buf1, "SYSERR: deleting edit file %s (2)", fname); perror(buf1); } } } // add ability to send string to client for editing // 2/25/98 -jtrhone if (PLR2_FLAGGED(ch, PLR2_CLIEDIT) && ch->desc && HAS_CLIENT(ch->desc)) cliedit = TRUE; if (*return_ptr) { if (PLR_FLAGGED(ch, PLR_EXEDIT)) string_to_file(*return_ptr, fname); else if (cliedit) { client_edit(ch->desc, prompt, *return_ptr); send_to_char("Switch to RoAClient...", ch); } free_log(*return_ptr, "do_max_string_arg"); } *return_ptr = NULL; MENU_HANDLER(ch) = menu_long_string; ch->desc->max_str = MAX_STRING_LENGTH - 3; ch->desc->str = return_ptr; if (PLR_FLAGGED(ch, PLR_EXEDIT)) { MENU_PROMPT(ch) = NULL; sprintf(shellfname, "%s.edit", GET_NAME(ch)); startshell(ch->desc, "", shellfname); } else if (cliedit) { MENU_PROMPT(ch) = NULL; } else { send_to_char(prompt, ch); MENU_PROMPT(ch) = NULL; } return 0; } // set character into classic string editting mode (like writing boards) // multi line text entry, will use cliedit now if chosen 7/9/98 -jtrhone int do_long_string_arg(chdata *ch, char *prompt, char **return_ptr) { BOOL cliedit = FALSE; menu_push(ch); if (PLR2_FLAGGED(ch, PLR2_CLIEDIT) && ch->desc && HAS_CLIENT(ch->desc)) cliedit = TRUE; if (*return_ptr) { if (cliedit) { client_edit(ch->desc, prompt, *return_ptr); send_to_char("Switch to RoAClient...", ch); } free_log(*return_ptr, "do_long_string_arg"); } *return_ptr = NULL; MENU_HANDLER(ch) = menu_long_string; ch->desc->max_str = 1000; ch->desc->str = return_ptr; if (!cliedit) send_to_char(prompt, ch); MENU_PROMPT(ch) = NULL; return 0; } // sends character into exshell editor if they are flagged to do so // currently used for mobprocs and IMPL room descrips perhaps int do_var_string_arg(chdata *ch, char *prompt, char **return_ptr, int length) { char shellfname[100]; char fname[100]; BOOL cliedit = FALSE; extern void startshell(dsdata *d, char *x, char *y); menu_push(ch); // RoA // OK, if using alternate editor for these large files // write the current *return_ptr to their edit file so // spico can read it if (PLR_FLAGGED(ch, PLR_EXEDIT)) { sprintf(fname, "edits/%s.edit", GET_NAME(ch)); unlink(fname); if (*return_ptr) string_to_file(*return_ptr, fname); } // add ability to send string to client for editing // 2/25/98 -jtrhone if (PLR2_FLAGGED(ch, PLR2_CLIEDIT) && ch->desc && HAS_CLIENT(ch->desc)) { cliedit = TRUE; client_edit(ch->desc, prompt, *return_ptr); send_to_char("Switch to RoAClient...", ch); } if (*return_ptr) free_log(*return_ptr, "do_var_string_arg"); *return_ptr = NULL; MENU_HANDLER(ch) = menu_long_string; ch->desc->max_str = length; ch->desc->str = return_ptr; if (PLR_FLAGGED(ch, PLR_EXEDIT)) { MENU_PROMPT(ch) = NULL; sprintf(shellfname, "%s.edit", GET_NAME(ch)); startshell(ch->desc, "", shellfname); } else if (cliedit) { MENU_PROMPT(ch) = NULL; } else { send_to_char(prompt, ch); MENU_PROMPT(ch) = NULL; } return 0; } // one line text entry int do_string_arg(chdata *ch, char *prompt, char **return_ptr, char *suffix) { struct menu_string_arg *arg; CREATE(arg, struct menu_string_arg, 1); menu_push(ch); MENU_HANDLER_ARG(ch) = (void *) arg; arg->return_ptr = return_ptr; arg->suffix = suffix; MENU_PROMPT(ch) = prompt; menu_jump(ch, menu_string); return 0; } int toggle_menu(chdata *ch, char *prompt, int *return_ptr, char **strings) { int i; struct menu_toggle_bits_arg *arg; CREATE(arg, struct menu_toggle_bits_arg, 1); menu_push(ch); MENU_HANDLER_ARG(ch) = (void *) arg; arg->bit_field = return_ptr; arg->bit_strs = strings; for (i = 0; *(strings[i]) != '\n'; i++) ; arg->n_bit_strs = i; MENU_PROMPT(ch) = prompt; menu_jump(ch, menu_toggle_bits); return 0; } /* same as toggle_menu but with long referenced */ int toggle_menu_long(chdata *ch, char *prompt, long *return_ptr, char **strings) { int i; struct menu_toggle_bits_long_arg *arg; CREATE(arg, struct menu_toggle_bits_long_arg, 1); menu_push(ch); MENU_HANDLER_ARG(ch) = (void *) arg; arg->bit_field = return_ptr; arg->bit_strs = strings; for (i = 0; *(strings[i]) != '\n'; i++) ; arg->n_bit_strs = i; MENU_PROMPT(ch) = prompt; menu_jump(ch, menu_toggle_bits_long); return 0; } int get_integer_arg(chdata *ch, char *prompt, void *return_ptr, int return_size, int min_value, int max_value) { struct menu_get_integer_arg *arg; CREATE(arg, struct menu_get_integer_arg, 1); menu_push(ch); MENU_HANDLER_ARG(ch) = (void *) arg; arg->min = min_value; arg->max = max_value; arg->size = return_size; arg->return_ptr = return_ptr; arg->strings = NULL; arg->n_strings = 0; arg->offset = 0; MENU_PROMPT(ch) = prompt; menu_jump(ch, menu_get_integer); return 0; } int get_integer_list(chdata *ch, char *prompt, void *return_ptr, int return_size, char **strings) { int i; struct menu_get_integer_arg *arg; CREATE(arg, struct menu_get_integer_arg, 1); menu_push(ch); MENU_HANDLER_ARG(ch) = (void *) arg; arg->min = 1; arg->offset = 1; arg->size = return_size; arg->return_ptr = return_ptr; arg->strings = strings; for (i = 0; *(strings[i]) != '\n'; i++) ; arg->n_strings = i; arg->max = i; MENU_PROMPT(ch) = prompt; menu_jump(ch, menu_get_integer); return 0; } // push a menu onto chars stack int menu_push(chdata *ch) { ch->desc->menu_args[MENU_DEPTH(ch)] = MENU_HANDLER_ARG(ch); ch->desc->menu_stack[MENU_DEPTH(ch)++] = MENU_HANDLER(ch); return 0; } // pop a menu off chars stack int menu_pop(chdata *ch) { MENU_HANDLER_ARG(ch) = ch->desc->menu_args[--MENU_DEPTH(ch)]; MENU_HANDLER(ch) = ch->desc->menu_stack[MENU_DEPTH(ch)]; return 0; } // pop menu off, and call menu int menu_back(chdata *ch) { menu_pop(ch); (*MENU_HANDLER(ch))(ch, NULL); return 0; } ROA_MENU(menu_long_string) { menu_back(ch); } ROA_MENU(menu_string) { struct menu_string_arg *arg = MENU_HANDLER_ARG(ch); if (input_str) { FREENULL(*arg->return_ptr); CREATE(*arg->return_ptr, char, strlen(input_str) + strlen(arg->suffix) + 1); strcpy(*arg->return_ptr, input_str); strcat(*arg->return_ptr, arg->suffix); FREENULL(MENU_HANDLER_ARG(ch)); menu_back(ch); } } ROA_MENU(menu_toggle_bits) { char buf[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char *p; int field; int i; struct menu_toggle_bits_arg *arg = MENU_HANDLER_ARG(ch); int level = GET_LEVEL(ch); if (!input_str) { menu_title_send("Flag Toggle Menu", ch); for (i = 0; i < arg->n_bit_strs; i++) { sprintf(buf, "%2d.) %%5%-20.20s%%0", i + 1, arg->bit_strs[i]); if (!((i+1) % 3)) strcat(buf, "\n\r"); send_to_char(buf, ch); } sprintbit(*arg->bit_field, arg->bit_strs, buf2); sprintf(buf, "\n\n\r%%6Bits set%%0: %%5%s%%0\n\r", buf2); send_to_char(buf, ch); return; } strcpy(buf2, input_str); // while numbers, set corresponding bits if (!*buf2) { FREENULL(MENU_HANDLER_ARG(ch)); menu_pop(ch); } else while (*buf2) { half_chop(buf2, buf, buf2); p = strtok(buf, " \n\r"); if (p) field = atoi(p); else field = 0; if (!field) { FREENULL(MENU_HANDLER_ARG(ch)); menu_pop(ch); break; } else if (field > 0 && field <= arg->n_bit_strs) { switch (*arg->bit_strs[field-1]) { case '*': // normally non editable if (level > LEV_IMPL) *arg->bit_field ^= (1 << (field - 1)); break; case '+': // aimp+ only if (level >= LEV_AIMP) *arg->bit_field ^= (1 << (field - 1)); break; default: // any builder can edit... *arg->bit_field ^= (1 << (field - 1)); break; } } } (*MENU_HANDLER(ch))(ch, NULL); } ROA_MENU(menu_toggle_bits_long) { char buf[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char *p; long field; int i; struct menu_toggle_bits_long_arg *arg = MENU_HANDLER_ARG(ch); int level = GET_LEVEL(ch); if (!input_str) { menu_title_send("Flag Toggle MenuII", ch); for (i = 0; i < arg->n_bit_strs; i++) { sprintf(buf, "%2d.) %%5%-20.20s%%0", i + 1, arg->bit_strs[i]); if (!((i+1) % 3)) strcat(buf, "\n\r"); send_to_char(buf, ch); } sprintbit(*arg->bit_field, arg->bit_strs, buf2); sprintf(buf, "\n\n\r%%6Bits set%%0: %%5%s%%0\n\r", buf2); send_to_char(buf, ch); return; } strcpy(buf2, input_str); // while numbers, set corresponding bits if (!*buf2) { FREENULL(MENU_HANDLER_ARG(ch)); menu_pop(ch); } else while (*buf2) { half_chop(buf2, buf, buf2); p = strtok(buf, " \n\r"); if (p) field = atoi(p); else field = 0; if (!field) { FREENULL(MENU_HANDLER_ARG(ch)); menu_pop(ch); } else if (field > 0 && field <= arg->n_bit_strs) { switch (*arg->bit_strs[field-1]) { case '*': // normally non editable if (level > LEV_IMPL) *arg->bit_field ^= ((long long) 1 << (field - 1)); break; case '+': // aimp+ only if (level >= LEV_AIMP) *arg->bit_field ^= ((long long) 1 << (field - 1)); break; default: // any builder can edit... *arg->bit_field ^= ((long long) 1 << (field - 1)); break; } } } (*MENU_HANDLER(ch))(ch, NULL); } ROA_MENU(menu_get_integer) { struct menu_get_integer_arg *arg = MENU_HANDLER_ARG(ch); char *p; int n; int i; if (!input_str) { menu_title_send("Generic Selection Menu", ch); for (i = 0; i < arg->n_strings; i++) { sprintf(buf, "%2d.) %%5%-21s%%0", i + 1, arg->strings[i]); if ((i % 3) == 2) strcat(buf, "\n\r"); send_to_char(buf, ch); } send_to_char("\n\r",ch); } else { p = strtok(input_str, " \n\r"); if (p) { n = atoi(p); if (n < arg->min || n > arg->max) { char buf[80]; sprintf(buf, "%%BValue must be in the range %d to %d%%0.\n\r", arg->min, arg->max); send_to_char(buf, ch); return; } n -= arg->offset; switch (arg->size) { case 1: *(char *)arg->return_ptr = n; break; case 2: *(short *)arg->return_ptr = n; break; case 4: *(int *)arg->return_ptr = n; break; } } FREENULL(MENU_HANDLER_ARG(ch)); menu_back(ch); } } /* for finding exits to void.. RoA*/ ACMD(do_voidlist) { rmdata *w; int zone, rnum; int i, top, dir; BOOL found = FALSE; if (IS_NPC(ch)) return; one_argument(argument, buf); if (!*buf || *buf == '.') zone = world[ch->in_room].zone; else zone = real_zone(atoi(buf)); if (zone < 0) { send_to_char("Zone does not exist.\n\r",ch); return; } if (!olc_perms(ch, LEV_GOD, zone)) return; top = zone_table[zone].top; for (i = zone * 100; i <= top; i++) { if (real_room(i) >= 0) break; } if (i > top) { send_to_char("No rooms in that zone.\n\r",ch); return; } while (i <= top) { if ((rnum = real_room(i)) < 0) { i++; continue; } w = &world[rnum]; for (dir=0; dir < 10; dir++) if (w->dir_option[dir]) if (w->dir_option[dir]->to_room < 1) { sprintf(buf, "Room %5d - %s exits to void.\n\r",i, dirs[dir]); send_to_char(buf, ch); found = TRUE; } if (w->drift_to > 0 && real_room(w->drift_to) < 0) { sprintf(buf, "Check room #%d drift to.\n\r",i); S2C(); found = TRUE; } if (w->float_to > 0 && real_room(w->float_to) < 0) { sprintf(buf, "Check room #%d float to.\n\r",i); S2C(); found = TRUE; } if (w->drop_to > 0 && real_room(w->drop_to) < 0) { sprintf(buf, "Check room #%d drop to.\n\r",i); S2C(); found = TRUE; } if (ROOM_FLAGGED(rnum, ALTERHIT | ALTERMANA | ALTERMOVE) && !ROOM_FLAGGED(rnum, DEATH | FLY_DEATH)) { if ((w->numdice + w->numdice * w->sizedice) / 2 >= 5) { sprintf(buf, "Room %5d - Dice exceed max average.\n\r",i); S2C(); } } i++; } if (!found) send_to_char("No void exits / invalid entries found.\n\r",ch); }