/************************************************************************ Realms of Aurealis James Rhone aka Vall of RoA screen.c VT100 emulation code, color code, vtmap code, vtsize code... all sorts of stuff dealing with a players screen... ******** 100% Completely Original Code ******** *** BE AWARE OF ALL RIGHTS AND RESERVATIONS *** ******** 100% Completely Original Code ******** All rights reserved henceforth. 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. RoA is based on both Diku and CircleMUD and ALL licenses from both *MUST* be adhered to as well as the RoA license. *** Read, Learn, Understand, Improve *** *************************************************************************/ #include "conf.h" #include "sysdep.h" #include "structures.h" #include "utils.h" #include "comm.h" #include "interpreter.h" #include "acmd.h" #include "handler.h" #include "db.h" #include "screen.h" #include "mudlimits.h" #include "lists.h" #include "global.h" // internals void update_vtmap(chdata *ch); /**********************************/ /**********************************/ /**********************************/ /* RoA color and VT100 term stuff */ /**********************************/ /**********************************/ /**********************************/ /* clears screen and homes to 0 0 */ void clrscr(chdata *ch) { send_to_char(CLRSCR, ch); if (VT100(ch)) init_vtbar(ch); } void clrline(chdata *ch) { if (ch->desc) send_to_q(CLRLINE, ch->desc); /* erase */ } /* sets scroll to 0 21 and inits the menu bar at bottom of screen */ void init_vtbar(chdata *ch) { if (IS_NPC(ch) || !ch->desc) return; // default vtsplit is 21 sprintf(buf, SCROLLAREA, 0, VTSPLIT(ch), VTSPLIT(ch), 0); S2C(); sprintf(buf, CURSPOS, VTSPLIT(ch) + 1, 0); S2C(); send_to_char(BARLINE, ch); sprintf(buf, CURSPOS, VTSPLIT(ch) + 2, 0); S2C(); sprintf(buf, " %%6%s%%0 ", longmudname); S2C(); sprintf(buf, CURSPOS, VTSPLIT(ch) + 2 + PSIZE(ch), 0); S2C(); send_to_char(BARLINE, ch); // now go back up top sprintf(buf, CURSPOS, VTSPLIT(ch), 0); S2C(); return; } // takes row and column, moves cursor there void cursor_goto(chdata *ch, int row, int col) { if (ch->desc) { CURSOR_ROW(ch) = row; CURSOR_COL(ch) = col; sprintf(buf, CURSPOS, CURSOR_ROW(ch), CURSOR_COL(ch)); send_to_q(buf, ch->desc); // send actual string } } void send_to_vtbar(char *messg, chdata *ch) { if (ch->desc && messg) { cursor_goto(ch, VTSPLIT(ch) + 2, 0); clrline(ch); send_to_q(messg, ch->desc); /* send message */ cursor_goto(ch, VTSPLIT(ch), 0); if (PLR_FLAGGED(ch, PLR_VTMAP)) update_vtmap(ch); // look in misc.c for now } return; } void updatescr(chdata *ch) { static char pstr[MAX_INPUT_LENGTH]; if (IS_NPC(ch) || IN_NOWHERE(ch)) return; *pstr = '\0'; display_prompt(ch, pstr); send_to_vtbar(pstr, ch); ch->pc_specials->needs_update = FALSE; } /* this clears the screen and sets scroll back to norm */ void resetscr(chdata *ch) { clrscr(ch); sprintf(buf, CLRSCROLLAREA, 0, VTSPLIT(ch) + 2 + PSIZE(ch)); S2C(); return; } // Mapping code, jtrhone aka vall RoA #define NOT_MAPPED 0 #define NOTHING_HERE 1 #define CHAR_HERE 2 /* following is for ascii mapping on RoA once again, innovations... James Rhone */ void map_room(int room, int ar[22][22], int xpos, int ypos, int depth, chdata *ch, BOOL zone_only) { int dir; /* are we at an edge ? */ if (!room || xpos > (11+depth) || xpos < (11-depth) || ypos > (11+depth) || ypos < (11-depth)) return; if (room == ch->in_room) ar[xpos][ypos] = CHAR_HERE; else ar[xpos][ypos] = NOTHING_HERE; /* now map all exits if not mapped already */ /* primary 4 dirs */ for (dir = 0; dir < 4; dir++) { if (DIR(room, dir) && !INVALID_ROOM(DIR(room, dir)->to_room)) { if (zone_only && world[DIR(room, dir)->to_room].zone != world[room].zone) continue; switch (dir) { case 0: /* north */ if (!ar[xpos][ypos-1]) map_room(world[room].dir_option[dir]->to_room, ar, xpos, (ypos-1), depth, ch, zone_only); break; case 1: /* east */ if (!ar[xpos+1][ypos]) map_room(world[room].dir_option[dir]->to_room, ar, (xpos+1), ypos, depth, ch, zone_only); break; case 2: /* south */ if (!ar[xpos][ypos+1]) map_room(world[room].dir_option[dir]->to_room, ar, xpos, (ypos+1), depth, ch, zone_only); break; case 3: /* west */ if (!ar[xpos-1][ypos]) map_room(world[room].dir_option[dir]->to_room, ar, (xpos-1), ypos, depth, ch, zone_only); break; } } } /* secondary 4 dirs */ for (dir = 6; dir < 10; dir++) { if (DIR(room, dir) && !INVALID_ROOM(DIR(room, dir)->to_room)) { if (zone_only && world[DIR(room, dir)->to_room].zone != world[room].zone) continue; switch (dir) { case 6: /* northeast */ if (!ar[xpos+1][ypos-1]) map_room(world[room].dir_option[dir]->to_room, ar, (xpos+1), (ypos-1), depth, ch, zone_only); break; case 7: /* southeast */ if (!ar[xpos+1][ypos+1]) map_room(world[room].dir_option[dir]->to_room, ar, (xpos+1), (ypos+1), depth, ch, zone_only); break; case 8: /* southwest */ if (!ar[xpos-1][ypos+1]) map_room(world[room].dir_option[dir]->to_room, ar, (xpos-1), (ypos+1), depth, ch, zone_only); break; case 9: /* northwest */ if (!ar[xpos-1][ypos-1]) map_room(world[room].dir_option[dir]->to_room, ar, (xpos-1), (ypos-1), depth, ch, zone_only); break; } } } return; } /* beta mapping stuff RoA James Rhone */ ACMD(do_map) { int depth, x, y; int ar[22][22]; byte xleft, xright, ytop, ybottom; char arg2[MAX_INPUT_LENGTH]; BOOL mark, zone_only; if (IS_NPC(ch)) return; half_chop(argument, arg, arg2); if (!*arg || !is_number(arg) || ((depth = atoi(arg)) < 2) || depth > 10) { send_to_char("Usage: map <depth between 2 and 10>.\n\r",ch); return; } if (*arg2 && is_abbrev(arg2, "zone")) zone_only = TRUE; else zone_only = FALSE; /* init array to 0 */ for(y = 0; y < 22; y++) for(x = 0; x < 22; x++) ar[x][y] = 0; map_room(ch->in_room, ar, 11, 11, depth, ch, zone_only); /* throw top line on map */ strcpy(buf, "\n\n\r%B"); for (x = 0; x < 2*depth+1; x++) strcat(buf, "-"); strcat(buf, "%0\n\r"); /* ok, now for map, if we in the depth ranges of x and y go ahead and throw a char into the buf, else ignore and move on... James Rhone */ xright = 11+depth; xleft = 11-depth; ytop = 11-depth; ybottom= 11+depth; for(y = 0; y < 22; y++) if ((y <= ybottom) && (y >= ytop)) { for(x = 0, mark = FALSE; x < 22; x++) if ((x <= xright) && (x >= xleft)) { if (ar[x][y]) mark = TRUE; switch (ar[x][y]) { case 0 : /* nothing here */ strcpy(buf2, " "); break; case 1 : /* hey, its a normal room here */ strcpy(buf2, "="); break; case 2 : /* ok, we got the mapper here.. */ strcpy(buf2, "%B*%0"); break; } strcat(buf, buf2); } if (mark) strcat(buf, "\n\r"); else strcat(buf, "\r"); } /* now for bottom line on it */ strcat(buf, "%B"); for (x = 0; x < 2*depth+1; x++) strcat(buf, "-"); strcat(buf, "%0\n\r"); S2C(); } /* KEWL STUFF, little vtmap up in the right corner for now :) -jtrhone roa */ void update_vtmap(chdata *ch) { int depth, x, y; int ar[22][22]; byte xleft, xright, ytop, ybottom; BOOL mark; int row, col; if (IS_NPC(ch)) return; depth = 3; // could be preference sometime /* init array to 0 */ for(y = 0; y < 22; y++) for(x = 0; x < 22; x++) ar[x][y] = 0; // send TRUE for zone_only by default until i make a FLAG for that // on characters map_room(ch->in_room, ar, 11, 11, depth, ch, TRUE); // init first row row = 2; col = 70; xright = 11+depth; xleft = 11-depth; ytop = 11-depth; ybottom= 11+depth; sprintf(buf, CURSPOS, row, col); strcat(buf, "%6---------%0"); sprintf(buf2, CURSPOS, ++row, col); strcat(buf, buf2); for(y = 0; y < 22; y++) if ((y <= ybottom) && (y >= ytop)) { strcat(buf, "%6|%0"); for(x = 0, mark = FALSE; x < 22; x++) if ((x <= xright) && (x >= xleft)) { if (ar[x][y]) mark = TRUE; switch (ar[x][y]) { case 0 : /* nothing here */ strcpy(buf2, " "); break; case 1 : /* hey, its a normal room here */ strcpy(buf2, "="); break; case 2 : /* ok, we got the mapper here.. */ strcpy(buf2, "%B*%0"); break; } strcat(buf, buf2); } if (mark) { strcat(buf, "%6|%0"); sprintf(buf2, CURSPOS, ++row, col); strcat(buf, buf2); } else { strcat(buf, "%6|%0"); sprintf(buf2, CURSPOS, row, col); strcat(buf, buf2); strcat(buf, " "); sprintf(buf2, CURSPOS, row, col); strcat(buf, buf2); } } strcat(buf, "%6---------%0"); sprintf(buf2, CURSPOS, VTSPLIT(ch), 0); strcat(buf, buf2); S2C(); } // toggle the vtmap on and off ACMD(do_vtmap) { if(IS_NPC(ch)) return; TOGGLE_BIT(PLR_FLAGS(ch), PLR_VTMAP); if (PLR_FLAGGED(ch, PLR_VTMAP)) send_to_char("%5VTmap activated%0.\r\n", ch); else send_to_char("%5VTmap deactivated%0.\r\n", ch); } ACMD(do_vt100) { int size; if (IS_NPC(ch)) return; one_argument(argument, arg); if (!*arg) { sprintf(buf, "VT100 emulation %s.\n\r",(VT100(ch)? "on":"off")); S2C(); if (VT100(ch)) sprintf(buf, "Current top screen size: %%5%d%%0 rows.\n\r", VTSPLIT(ch)); return; } if (!is_number(arg) && str_cmp(arg, "+") && str_cmp(arg, "-")) { send_to_char ("Usage: vt100 {<number> | %B+%0 | %B-%0}\n\r", ch); return; } if (is_number(arg)) { size = atoi(arg); if (size < 10 || size > 100) { send_to_char("Value must be range between 10 and 100.\n\r",ch); return; } VTSPLIT(ch) = size; clrscr(ch); sprintf(buf, "Top screen size changed to %%5%d%%0 rows.\n\r",size); S2C(); return; } ch->pc_specials->saved.vt100 = FALSE; if (!str_cmp(arg, "+")) { SET_BIT(PRF_FLAGS(ch), PRF_COLOR); ch->pc_specials->saved.vt100 = TRUE; init_vtbar(ch); } if (!VT100(ch)) resetscr(ch); sprintf (buf, "VT100 emulation is now %s.\n\r",(VT100(ch)? "on":"off")); S2C(); if (VT100(ch)) { sprintf(buf, "Current top screen size: %%5%d%%0 rows.\n\r", VTSPLIT(ch)); S2C(); } } ACMD(do_page_length) { int len; char *argu = argument; skip_spaces(&argu); if (!*argu) { sprintf(buf, "Current page length: %%6%d%%0 lines.\n\r",PAGE_LENGTH(ch)); S2C(); return; } if (!is_number(argu)) { send_to_char("Usage: pagelength < # of lines >.\n\r",ch); return; } len = atoi(argu); if (len < 15 || len > 40) { send_to_char("Page length must be between 15 and 40 lines.\n\r",ch); return; } PAGE_LENGTH(ch) = len; sprintf(buf, "Page length changed to %%6%d%%0 lines.\n\r",len); S2C(); } // adjust both vt100 screen top size and lower menu size ACMD(do_vtsize) { int size; if (IS_NPC(ch)) return; half_chop(argument, arg, buf2); if (!*arg) { send_to_char("Usage: vtsize <top # rows> <bottom # rows>\n\r",ch); sprintf(buf, "VT100 emulation currently %%5%s%%0.\n\r", (VT100(ch)?"on":"off")); S2C(); if (VT100(ch)) { sprintf(buf, "Current # of top rows: %%5%d%%0 rows.\n\r", VTSPLIT(ch)); S2C(); sprintf(buf, "Current # of bot rows: %%5%d%%0 lines.\n\r", PSIZE(ch)); S2C(); } return; } if (!is_number(arg)) { send_to_char("Usage: vtsize <top # rows> <bottom # rows>\n\r",ch); return; } size = atoi(arg); if (size < 10 || size > 100) { send_to_char("Top must be between 10 - 100 lines.\n\r",ch); return; } VTSPLIT(ch) = size; if (*buf2) { if(!is_number(buf2)) { send_to_char("Usage: vtsize <top # rows> <bottom # rows>\n\r",ch); return; } size = atoi(buf2); if (size < 1 || size > 10) { send_to_char("Bottom must be between 1 - 10 lines.\n\r",ch); return; } PSIZE(ch) = size; } clrscr(ch); if (VT100(ch)) { sprintf(buf, "%%6%%BVT100%%0 resize: Top %d, Bottom %d.\n\r", VTSPLIT(ch),PSIZE(ch)); S2C(); } } /********************************************************/ /* The following is for interpreting COLOR strings */ /* encoded %1 - %7 based on colors... uses basic prompt */ /* decoding... JTRHONE ROA */ /********************************************************/ /* killp removes the % symbols from a string unless there is two consecutive symbols of such, such as %% in which ONE will remain in the string at that point. This is used for people with color OFF so they can ignore the color code sequences that we (RoA) use. JTRHONE NOTE: It also removes the character after the % so for example %1 it would remove both the % and the 1 */ void killp(char *str) { char *tmp1, *tmp2; for (tmp1 = str; *tmp1; tmp1++) { /* if double percentage, keep one of them */ if (*tmp1 == '%' && (*(tmp1+1) && *(tmp1+1) == '%')) { for (tmp2 = tmp1 + 1; *tmp2; tmp2++) *(tmp2 - 1) = *tmp2; *(tmp2 - 1) = '\0'; continue; } else while (*tmp1 == '%' && (*(tmp1+1) && *(tmp1+1) != '%')) { /* kill the percent */ for (tmp2 = tmp1 + 1; *tmp2; tmp2++) *(tmp2 - 1) = *tmp2; *(tmp2 - 1) = '\0'; /* now kill what was after it */ for (tmp2 = tmp1 + 1; *tmp2; tmp2++) *(tmp2 - 1) = *tmp2; *(tmp2 - 1) = '\0'; } } } // updated to return delta chars from newstr to oldstr int color_decode(chdata *orig, char *pstr, char *newstr) { char *pstring = pstr; chdata *ch; int cnt = 0; if(!*pstring) return 0; if (strlen(pstring) > MAX_STRING_LENGTH) { strcpy(newstr, "MaxLength EXCEEDED. Notify VALL immediately."); return 0; } ch = (orig->desc && orig->desc->original) ? orig->desc->original : orig; if (IS_NPC(ch)) { strcpy(newstr,pstr); return 0; } if (!ANSI(ch)) { strcpy(newstr, pstr); killp(newstr); return 0; } *newstr = '\0'; while(*pstring) { if(*pstring != '%') { sprintf(newstr, "%s%c", newstr, *pstring); pstring++; continue; } pstring++; switch(*pstring) { case '%': strcat(newstr, "%"); pstring++; cnt++; break; /* case ']': strcat(newstr, KBLK); pstring++; break; case 'r': case '}': strcat(newstr, KREV); pstring++; break; case '{': strcat(newstr, KCON); pstring++; break; */ case 'F': /* faint? */ strcat(newstr, KFAI); pstring++; break; case 'I': /* italics never happenin */ strcat(newstr, KITA); pstring++; break; case 'B': case 'b': /* bold */ strcat(newstr, KBLD); pstring++; cnt += strlen(KBLD); break; case '0': strcat(newstr, KNRM); pstring++; cnt += strlen(KNRM); break; case '1': strcat(newstr, KRED); pstring++; cnt += strlen(KRED); break; case '2': strcat(newstr, KGRN); pstring++; cnt += strlen(KGRN); break; case '3': strcat(newstr, KYEL); pstring++; cnt += strlen(KYEL); break; case '4': strcat(newstr, KBLU); pstring++; cnt += strlen(KBLU); break; case '5': strcat(newstr, KMAG); pstring++; cnt += strlen(KMAG); break; case '6': strcat(newstr, KCYN); pstring++; cnt += strlen(KCYN); break; case '7': strcat(newstr, KWHT); pstring++; cnt += strlen(KWHT); break; case '8': /* dark grey */ strcat(newstr, KBLA); pstring++; cnt += strlen(KBLA); break; default: break; } } strcat(newstr, KNRM); return cnt; } ACMD(do_color) { if (IS_NPC(ch)) return; one_argument(argument, arg); if (!*arg) { sprintf(buf, "Your color is %s.\n\r",(ANSI(ch)? "ON":"OFF")); send_to_char(buf, ch); return; } if (*arg != '+' && *arg != '-') { send_to_char ("Usage: color {+|-}\n\r", ch); return; } REMOVE_BIT(PRF_FLAGS(ch), PRF_COLOR); if (*arg == '+') SET_BIT(PRF_FLAGS(ch), PRF_COLOR); sprintf (buf, "Your %%6color%%0 is now %s.\n\r",(ANSI(ch)? "ON":"OFF")); S2C(); }