diff options
author | skotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2006-11-07 20:56:28 +0000 |
---|---|---|
committer | skotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2006-11-07 20:56:28 +0000 |
commit | f0fef787616b240f4d4dece0973ec20b3464a0e7 (patch) | |
tree | cf8ee0ca6d5890b35f07ac0421ae93153695f728 | |
parent | 4e7bd03012431ebb2f308e3667db41a883b1041e (diff) | |
download | hercules-f0fef787616b240f4d4dece0973ec20b3464a0e7.tar.gz hercules-f0fef787616b240f4d4dece0973ec20b3464a0e7.tar.bz2 hercules-f0fef787616b240f4d4dece0973ec20b3464a0e7.tar.xz hercules-f0fef787616b240f4d4dece0973ec20b3464a0e7.zip |
- Applied FlavioJs's patch which enables colored console output for Windows systems. It also includes a config setting called "stdout_with_ansisequence" with which you can turn off the color codes (in case you are logging all output)
- Added error reporting when the max number of ground unit cells has been reached (this may be the reason why sometimes it fails to recognize when you step out of a song/dance/encore)
- Added passing the Endure effect to other devoted people. Note that the "hit count" is individual for each character, and only when it ends on the Crusader himself will that force it to end on everyone else. It also will not transfer on gvg grounds, but it does transfer in pvp.
- Fixed Reflect-Shield triggering Auto-Guard instead on devoted chars.
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@9168 54d463be-8e91-2dee-dedb-b68131a5f0ec
-rw-r--r-- | Changelog-Trunk.txt | 13 | ||||
-rw-r--r-- | conf-tmpl/Changelog.txt | 6 | ||||
-rw-r--r-- | conf-tmpl/char_athena.conf | 8 | ||||
-rw-r--r-- | conf-tmpl/login_athena.conf | 8 | ||||
-rw-r--r-- | conf-tmpl/map_athena.conf | 8 | ||||
-rw-r--r-- | src/char/char.c | 2 | ||||
-rw-r--r-- | src/char_sql/char.c | 2 | ||||
-rw-r--r-- | src/common/showmsg.c | 739 | ||||
-rw-r--r-- | src/common/showmsg.h | 94 | ||||
-rw-r--r-- | src/login/login.c | 2 | ||||
-rw-r--r-- | src/login_sql/login.c | 2 | ||||
-rw-r--r-- | src/map/map.c | 14 | ||||
-rw-r--r-- | src/map/skill.c | 17 | ||||
-rw-r--r-- | src/map/status.c | 47 |
14 files changed, 832 insertions, 130 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index bb70c1719..32b557c75 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -4,6 +4,19 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2006/11/07
+ * Applied FlavioJs's patch which enables colored console output for Windows
+ systems. It also includes a config setting called
+ "stdout_with_ansisequence" with which you can turn off the color codes (in
+ case you are logging all output) [Skotlex]
+ * Added error reporting when the max number of ground unit cells has been
+ reached (this may be the reason why sometimes it fails to recognize when
+ you step out of a song/dance/encore) [Skotlex]
+ * Added passing the Endure effect to other devoted people. Note that the
+ "hit count" is individual for each character, and only when it ends on the
+ Crusader himself will that force it to end on everyone else. It also will
+ not transfer on gvg grounds, but it does transfer in pvp. [Skotlex]
+ * Fixed Reflect-Shield triggering Auto-Guard instead on devoted chars.
+ [Skotlex]
* Added a check to prevent casting ground skills on a target and vice-versa
when said skill use packets are received. It really shouldn't be
exploitable, but doing that certainly makes the server print a lot of
diff --git a/conf-tmpl/Changelog.txt b/conf-tmpl/Changelog.txt index 7d7189082..9cbc4cedb 100644 --- a/conf-tmpl/Changelog.txt +++ b/conf-tmpl/Changelog.txt @@ -1,5 +1,11 @@ Date Added
+2006/11/07
+ * New Setting "stdout_with_ansisequence"
+ (login_athena/char_athena/map_athena) allows you to specify whether color
+ control chars should be printed or not. Is useful to disable for a
+ "cleaner" output when you are logging the console output. All credit goes
+ to FlavioJS for coding the whole thing. [Skotlex]
2006/11/05
* Added maplags for PowerNPC quest. [KarLaeda]
2006/10/31
diff --git a/conf-tmpl/char_athena.conf b/conf-tmpl/char_athena.conf index c48c92138..840c40d2e 100644 --- a/conf-tmpl/char_athena.conf +++ b/conf-tmpl/char_athena.conf @@ -47,6 +47,14 @@ char_port: 6121 //For full format information, consult the strftime() manual.
//timestamp_format: [%d/%b %H:%M]
+//Defines if the ansi sequences should be parsed or skipped.
+//If set to yes the console output is in color. If the stream is redirected to
+//a file, the ansi sequences are printed out.
+//If set to no the console is colorless and, if redirected, will skip the ansi
+//sequences.
+//NOTE: this setting applyes for both stdout and stderr
+stdout_with_ansisequence: yes
+
//Makes server output more silent by ommitting certain types of messages:
//1: Hide Information messages
//2: Hide Status messages
diff --git a/conf-tmpl/login_athena.conf b/conf-tmpl/login_athena.conf index 41995a2db..834904a89 100644 --- a/conf-tmpl/login_athena.conf +++ b/conf-tmpl/login_athena.conf @@ -22,6 +22,14 @@ login_port: 6900 //For full format information, consult the strftime() manual.
//timestamp_format: [%d/%b %H:%M]
+//Defines if the ansi sequences should be parsed or skipped.
+//If set to yes the console output is in color. If the stream is redirected to
+//a file, the ansi sequences are printed out.
+//If set to no the console is colorless and, if redirected, will skip the ansi
+//sequences.
+//NOTE: this setting applyes for both stdout and stderr
+stdout_with_ansisequence: yes
+
//Makes server output more silent by ommitting certain types of messages:
//1: Hide Information messages
//2: Hide Status messages
diff --git a/conf-tmpl/map_athena.conf b/conf-tmpl/map_athena.conf index ee9fc4ae8..4812e5d1c 100644 --- a/conf-tmpl/map_athena.conf +++ b/conf-tmpl/map_athena.conf @@ -57,6 +57,14 @@ map_port: 5121 //For full format information, consult the strftime() manual.
//timestamp_format: [%d/%b %H:%M]
+//Defines if the ansi sequences should be parsed or skipped.
+//If set to yes the console output is in color. If the stream is redirected to
+//a file, the ansi sequences are printed out.
+//If set to no the console is colorless and, if redirected, will skip the ansi
+//sequences.
+//NOTE: this setting applyes for both stdout and stderr
+stdout_with_ansisequence: yes
+
//Makes server output more silent by ommitting certain types of messages:
//1: Hide Information messages
//2: Hide Status messages
diff --git a/src/char/char.c b/src/char/char.c index 0cc15a462..6e96ec0f0 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -4100,6 +4100,8 @@ int char_config_read(const char *cfgName) { remove_control_chars((unsigned char *)w2);
if(strcmpi(w1,"timestamp_format") == 0) {
strncpy(timestamp_format, w2, 20);
+ } else if(strcmpi(w1,"stdout_with_ansisequence")==0){
+ stdout_with_ansisequence = config_switch(w2);
} else if(strcmpi(w1,"console_silent")==0){
msg_silent = 0; //To always allow the next line to show up.
ShowInfo("Console Silent Setting: %d\n", atoi(w2));
diff --git a/src/char_sql/char.c b/src/char_sql/char.c index 1fbbf44aa..b2395623b 100644 --- a/src/char_sql/char.c +++ b/src/char_sql/char.c @@ -4030,6 +4030,8 @@ int char_config_read(const char *cfgName) { remove_control_chars((unsigned char *) w2);
if(strcmpi(w1,"timestamp_format")==0) {
strncpy(timestamp_format, w2, 20);
+ } else if(strcmpi(w1,"stdout_with_ansisequence")==0){
+ stdout_with_ansisequence = config_switch(w2);
} else if(strcmpi(w1,"console_silent")==0){
msg_silent = 0; //To always allow the next line to show up.
ShowInfo("Console Silent Setting: %d\n", atoi(w2));
diff --git a/src/common/showmsg.c b/src/common/showmsg.c index 594234b8d..b0f1d1d8f 100644 --- a/src/common/showmsg.c +++ b/src/common/showmsg.c @@ -5,9 +5,14 @@ #include <string.h>
#include <stdarg.h>
#include <time.h>
+#include <stdlib.h> // atexit
+#include "../common/cbasetypes.h"
#include "showmsg.h"
#ifdef _WIN32
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+
#ifdef DEBUGLOGMAP
#define DEBUGLOGPATH "log\\map-server.log"
#else
@@ -20,6 +25,9 @@ #endif
#endif
#else
+ #include <unistd.h>
+ #include <ctype.h>
+
#ifdef DEBUGLOGMAP
#define DEBUGLOGPATH "log/map-server.log"
#else
@@ -33,9 +41,605 @@ #endif
#endif
+///////////////////////////////////////////////////////////////////////////////
+/// behavioral parameter.
+/// when true, prints ansi sequences also when redirecting outputs to file
+/// otherwise remove them
+int stdout_with_ansisequence = 1;
+
int msg_silent; //Specifies how silent the console is.
-char tmp_output[1024] = {"\0"};
+
+///////////////////////////////////////////////////////////////////////////////
+/// small reallocating temporary printer buffer
+static char *tempbuf = NULL;
+static size_t sz = 0;
+#define tempbuf_size() (sz)
+static void tempbuf_free(void){ free(tempbuf); }
+static void tempbuf_alloc(void){ sz = 256; tempbuf = (char *)malloc(sz); atexit(tempbuf_free); }
+static void tempbuf_realloc(void){ sz <<= 1; tempbuf = (char *)realloc(tempbuf,sz); }
+
+///////////////////////////////////////////////////////////////////////////////
+#ifdef _WIN32
+// XXX adapted from eApp (comments are left untouched) [flaviojs]
+
+///////////////////////////////////////////////////////////////////////////////
+// ansi compatible printf with control sequence parser for windows
+// fast hack, handle with care, not everything implemented
+//
+// \033[#;...;#m - Set Graphics Rendition (SGR)
+//
+// printf("\x1b[1;31;40m"); // Bright red on black
+// printf("\x1b[3;33;45m"); // Blinking yellow on magenta (blink not implemented)
+// printf("\x1b[1;30;47m"); // Bright black (grey) on dim white
+//
+// Style Foreground Background
+// 1st Digit 2nd Digit 3rd Digit RGB
+// 0 - Reset 30 - Black 40 - Black 000
+// 1 - FG Bright 31 - Red 41 - Red 100
+// 2 - Unknown 32 - Green 42 - Green 010
+// 3 - Blink 33 - Yellow 43 - Yellow 110
+// 4 - Underline 34 - Blue 44 - Blue 001
+// 5 - BG Bright 35 - Magenta 45 - Magenta 101
+// 6 - Unknown 36 - Cyan 46 - Cyan 011
+// 7 - Reverse 37 - White 47 - White 111
+// 8 - Concealed (invisible)
+//
+// \033[#A - Cursor Up (CUU)
+// Moves the cursor up by the specified number of lines without changing columns.
+// If the cursor is already on the top line, this sequence is ignored. \e[A is equivalent to \e[1A.
+//
+// \033[#B - Cursor Down (CUD)
+// Moves the cursor down by the specified number of lines without changing columns.
+// If the cursor is already on the bottom line, this sequence is ignored. \e[B is equivalent to \e[1B.
+//
+// \033[#C - Cursor Forward (CUF)
+// Moves the cursor forward by the specified number of columns without changing lines.
+// If the cursor is already in the rightmost column, this sequence is ignored. \e[C is equivalent to \e[1C.
+//
+// \033[#D - Cursor Backward (CUB)
+// Moves the cursor back by the specified number of columns without changing lines.
+// If the cursor is already in the leftmost column, this sequence is ignored. \e[D is equivalent to \e[1D.
+//
+// \033[#E - Cursor Next Line (CNL)
+// Moves the cursor down the indicated # of rows, to column 1. \e[E is equivalent to \e[1E.
+//
+// \033[#F - Cursor Preceding Line (CPL)
+// Moves the cursor up the indicated # of rows, to column 1. \e[F is equivalent to \e[1F.
+//
+// \033[#G - Cursor Horizontal Absolute (CHA)
+// Moves the cursor to indicated column in current row. \e[G is equivalent to \e[1G.
+//
+// \033[#;#H - Cursor Position (CUP)
+// Moves the cursor to the specified position. The first # specifies the line number,
+// the second # specifies the column. If you do not specify a position, the cursor moves to the home position:
+// the upper-left corner of the screen (line 1, column 1).
+//
+// \033[#;#f - Horizontal & Vertical Position
+// (same as \033[#;#H)
+//
+// \033[s - Save Cursor Position (SCP)
+// The current cursor position is saved.
+//
+// \033[u - Restore cursor position (RCP)
+// Restores the cursor position saved with the (SCP) sequence \033[s.
+// (addition, restore to 0,0 if nothinh was saved before)
+//
+
+// \033[#J - Erase Display (ED)
+// Clears the screen and moves to the home position
+// \033[0J - Clears the screen from cursor to end of display. The cursor position is unchanged. (default)
+// \033[1J - Clears the screen from start to cursor. The cursor position is unchanged.
+// \033[2J - Clears the screen and moves the cursor to the home position (line 1, column 1).
+//
+// \033[#K - Erase Line (EL)
+// Clears the current line from the cursor position
+// \033[0K - Clears all characters from the cursor position to the end of the line (including the character at the cursor position). The cursor position is unchanged. (default)
+// \033[1K - Clears all characters from start of line to the cursor position. (including the character at the cursor position). The cursor position is unchanged.
+// \033[2K - Clears all characters of the whole line. The cursor position is unchanged.
+
+
+/*
+not implemented
+
+\033[#L
+IL: Insert Lines: The cursor line and all lines below it move down # lines, leaving blank space. The cursor position is unchanged. The bottommost # lines are lost. \e[L is equivalent to \e[1L.
+\033[#M
+DL: Delete Line: The block of # lines at and below the cursor are deleted; all lines below them move up # lines to fill in the gap, leaving # blank lines at the bottom of the screen. The cursor position is unchanged. \e[M is equivalent to \e[1M.
+\033[#\@
+ICH: Insert CHaracter: The cursor character and all characters to the right of it move right # columns, leaving behind blank space. The cursor position is unchanged. The rightmost # characters on the line are lost. \e[\@ is equivalent to \e[1\@.
+\033[#P
+DCH: Delete CHaracter: The block of # characters at and to the right of the cursor are deleted; all characters to the right of it move left # columns, leaving behind blank space. The cursor position is unchanged. \e[P is equivalent to \e[1P.
+
+Escape sequences for Select Character Set
+*/
+
+#define is_console(handle) (FILE_TYPE_CHAR==GetFileType(handle))
+
+///////////////////////////////////////////////////////////////////////////////
+int VFPRINTF(HANDLE handle, const char *fmt, va_list argptr)
+{
+ /////////////////////////////////////////////////////////////////
+ /* XXX Two streams are being used. Disabled to avoid inconsistency [flaviojs]
+ static COORD saveposition = {0,0};
+ */
+
+ /////////////////////////////////////////////////////////////////
+ unsigned long written;
+ char *p, *q;
+
+ if(!fmt || !*fmt)
+ return 0;
+
+ if(tempbuf == NULL)
+ tempbuf_alloc();
+ for(; vsnprintf(tempbuf, tempbuf_size(), fmt, argptr)<0; tempbuf_realloc());
+ // vsnprintf returns -1 in case of insufficient buffer size
+ // tempbuf_realloc doubles the size of the buffer in this case
+
+ if( !is_console(handle) && stdout_with_ansisequence )
+ {
+ WriteFile(handle,tempbuf, strlen(tempbuf), &written, 0);
+ return 0;
+ }
+
+ // start with processing
+ p = tempbuf;
+ while ((q = strchr(p, 0x1b)) != NULL)
+ { // find the escape character
+ if( 0==WriteConsole(handle, p, q-p, &written, 0) ) // write up to the escape
+ WriteFile(handle, p, q-p, &written, 0);
+
+ if( q[1]!='[' )
+ { // write the escape char (whatever purpose it has)
+ if(0==WriteConsole(handle, q, 1, &written, 0) )
+ WriteFile(handle,q, 1, &written, 0);
+ p=q+1; //and start searching again
+ }
+ else
+ { // from here, we will skip the '\033['
+ // we break at the first unprocessible position
+ // assuming regular text is starting there
+ uchar numbers[16], numpoint=0;
+ CONSOLE_SCREEN_BUFFER_INFO info;
+
+ // initialize
+ GetConsoleScreenBufferInfo(handle, &info);
+ memset(numbers,0,sizeof(numbers));
+
+ // skip escape and bracket
+ q=q+2;
+ while(1)
+ {
+ if( isdigit((int)((unsigned char)*q)) )
+ { // add number to number array, only accept 2digits, shift out the rest
+ // so // \033[123456789m will become \033[89m
+ numbers[numpoint] = (numbers[numpoint]<<4) | (*q-'0');
+ ++q;
+ // and next character
+ continue;
+ }
+ else if( *q == ';' )
+ { // delimiter
+ if(numpoint<sizeof(numbers)/sizeof(*numbers))
+ { // go to next array position
+ numpoint++;
+ }
+ else
+ { // array is full, so we 'forget' the first value
+ memmove(numbers,numbers+1,sizeof(numbers)/sizeof(*numbers)-1);
+ numbers[sizeof(numbers)/sizeof(*numbers)-1]=0;
+ }
+ ++q;
+ // and next number
+ continue;
+ }
+ else if( *q == 'm' )
+ { // \033[#;...;#m - Set Graphics Rendition (SGR)
+ uint i;
+ for(i=0; i<= numpoint; ++i)
+ {
+ if( 0x00 == (0xF0 & numbers[i]) )
+ { // upper nibble 0
+ if( 0 == numbers[i] )
+ { // reset
+ info.wAttributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
+ }
+ else if( 1==numbers[i] )
+ { // set foreground intensity
+ info.wAttributes |= FOREGROUND_INTENSITY;
+ }
+ else if( 5==numbers[i] )
+ { // set background intensity
+ info.wAttributes |= BACKGROUND_INTENSITY;
+ }
+ else if( 7==numbers[i] )
+ { // reverse colors (just xor them)
+ info.wAttributes ^= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE |
+ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
+ }
+ //case '2': // not existing
+ //case '3': // blinking (not implemented)
+ //case '4': // unterline (not implemented)
+ //case '6': // not existing
+ //case '8': // concealed (not implemented)
+ //case '9': // not existing
+ }
+ else if( 0x20 == (0xF0 & numbers[i]) )
+ { // off
+
+ if( 1==numbers[i] )
+ { // set foreground intensity off
+ info.wAttributes &= ~FOREGROUND_INTENSITY;
+ }
+ else if( 5==numbers[i] )
+ { // set background intensity off
+ info.wAttributes &= ~BACKGROUND_INTENSITY;
+ }
+ else if( 7==numbers[i] )
+ { // reverse colors (just xor them)
+ info.wAttributes ^= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE |
+ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
+ }
+ }
+ else if( 0x30 == (0xF0 & numbers[i]) )
+ { // foreground
+ uint num = numbers[i]&0x0F;
+ if(num==9) info.wAttributes |= FOREGROUND_INTENSITY;
+ if(num>7) num=7; // set white for 37, 38 and 39
+ info.wAttributes &= ~(FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);
+ if( (num & 0x01)>0 ) // lowest bit set = red
+ info.wAttributes |= FOREGROUND_RED;
+ if( (num & 0x02)>0 ) // second bit set = green
+ info.wAttributes |= FOREGROUND_GREEN;
+ if( (num & 0x04)>0 ) // third bit set = blue
+ info.wAttributes |= FOREGROUND_BLUE;
+ }
+ else if( 0x40 == (0xF0 & numbers[i]) )
+ { // background
+ uint num = numbers[i]&0x0F;
+ if(num==9) info.wAttributes |= BACKGROUND_INTENSITY;
+ if(num>7) num=7; // set white for 47, 48 and 49
+ info.wAttributes &= ~(BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE);
+ if( (num & 0x01)>0 ) // lowest bit set = red
+ info.wAttributes |= BACKGROUND_RED;
+ if( (num & 0x02)>0 ) // second bit set = green
+ info.wAttributes |= BACKGROUND_GREEN;
+ if( (num & 0x04)>0 ) // third bit set = blue
+ info.wAttributes |= BACKGROUND_BLUE;
+ }
+ }
+ // set the attributes
+ SetConsoleTextAttribute(handle, info.wAttributes);
+ }
+ else if( *q=='J' )
+ { // \033[#J - Erase Display (ED)
+ // \033[0J - Clears the screen from cursor to end of display. The cursor position is unchanged.
+ // \033[1J - Clears the screen from start to cursor. The cursor position is unchanged.
+ // \033[2J - Clears the screen and moves the cursor to the home position (line 1, column 1).
+ uint num = (numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F);
+ int cnt;
+ COORD origin = {0,0};
+ if(num==1)
+ { // chars from start up to and including cursor
+ cnt = info.dwSize.X * info.dwCursorPosition.Y + info.dwCursorPosition.X + 1;
+ }
+ else if(num==2)
+ { // Number of chars on screen.
+ cnt = info.dwSize.X * info.dwSize.Y;
+ SetConsoleCursorPosition(handle, origin);
+ }
+ else// 0 and default
+ { // number of chars from cursor to end
+ origin = info.dwCursorPosition;
+ cnt = info.dwSize.X * (info.dwSize.Y - info.dwCursorPosition.Y) - info.dwCursorPosition.X;
+ }
+ FillConsoleOutputAttribute(handle,info.wAttributes,cnt,origin,NULL);
+ FillConsoleOutputCharacter(handle,' ', cnt,origin,NULL);
+ }
+ else if( *q=='K' )
+ { // \033[K : clear line from actual position to end of the line
+ // \033[0K - Clears all characters from the cursor position to the end of the line.
+ // \033[1K - Clears all characters from start of line to the cursor position.
+ // \033[2K - Clears all characters of the whole line.
+
+ uint num = (numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F);
+ COORD origin = {0,info.dwCursorPosition.Y};
+ SHORT cnt;
+ if(num==1)
+ {
+ cnt = info.dwCursorPosition.X + 1;
+ }
+ else if(num==2)
+ {
+ cnt = info.dwSize.X;
+ }
+ else// 0 and default
+ {
+ origin = info.dwCursorPosition;
+ cnt = info.dwSize.X - info.dwCursorPosition.X; // how many spaces until line is full
+ }
+ FillConsoleOutputAttribute(handle, info.wAttributes, cnt, origin, NULL);
+ FillConsoleOutputCharacter(handle, ' ', cnt, origin, NULL);
+ }
+ else if( *q == 'H' || *q == 'f' )
+ { // \033[#;#H - Cursor Position (CUP)
+ // \033[#;#f - Horizontal & Vertical Position
+ // The first # specifies the line number, the second # specifies the column.
+ // The default for both is 1
+ info.dwCursorPosition.X = (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F-1):0;
+ info.dwCursorPosition.Y = (numpoint && numbers[numpoint-1])?(numbers[numpoint-1]>>4)*10+(numbers[numpoint-1]&0x0F-1):0;
+
+ if( info.dwCursorPosition.X >= info.dwSize.X ) info.dwCursorPosition.Y = info.dwSize.X-1;
+ if( info.dwCursorPosition.Y >= info.dwSize.Y ) info.dwCursorPosition.Y = info.dwSize.Y-1;
+ SetConsoleCursorPosition(handle, info.dwCursorPosition);
+ }
+ else if( *q=='s' )
+ { // \033[s - Save Cursor Position (SCP)
+ /* XXX Two streams are being used. Disabled to avoid inconsistency [flaviojs]
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ GetConsoleScreenBufferInfo(handle, &info);
+ saveposition = info.dwCursorPosition;
+ */
+ }
+ else if( *q=='u' )
+ { // \033[u - Restore cursor position (RCP)
+ /* XXX Two streams are being used. Disabled to avoid inconsistency [flaviojs]
+ SetConsoleCursorPosition(handle, saveposition);
+ */
+ }
+ else if( *q == 'A' )
+ { // \033[#A - Cursor Up (CUU)
+ // Moves the cursor UP # number of lines
+ info.dwCursorPosition.Y -= (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F):1;
+
+ if( info.dwCursorPosition.Y < 0 )
+ info.dwCursorPosition.Y = 0;
+ SetConsoleCursorPosition(handle, info.dwCursorPosition);
+ }
+ else if( *q == 'B' )
+ { // \033[#B - Cursor Down (CUD)
+ // Moves the cursor DOWN # number of lines
+ info.dwCursorPosition.Y += (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F):1;
+
+ if( info.dwCursorPosition.Y >= info.dwSize.Y )
+ info.dwCursorPosition.Y = info.dwSize.Y-1;
+ SetConsoleCursorPosition(handle, info.dwCursorPosition);
+ }
+ else if( *q == 'C' )
+ { // \033[#C - Cursor Forward (CUF)
+ // Moves the cursor RIGHT # number of columns
+ info.dwCursorPosition.X += (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F):1;
+
+ if( info.dwCursorPosition.X >= info.dwSize.X )
+ info.dwCursorPosition.X = info.dwSize.X-1;
+ SetConsoleCursorPosition(handle, info.dwCursorPosition);
+ }
+ else if( *q == 'D' )
+ { // \033[#D - Cursor Backward (CUB)
+ // Moves the cursor LEFT # number of columns
+ info.dwCursorPosition.X -= (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F):1;
+
+ if( info.dwCursorPosition.X < 0 )
+ info.dwCursorPosition.X = 0;
+ SetConsoleCursorPosition(handle, info.dwCursorPosition);
+ }
+ else if( *q == 'E' )
+ { // \033[#E - Cursor Next Line (CNL)
+ // Moves the cursor down the indicated # of rows, to column 1
+ info.dwCursorPosition.Y += (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F):1;
+ info.dwCursorPosition.X = 0;
+
+ if( info.dwCursorPosition.Y >= info.dwSize.Y )
+ info.dwCursorPosition.Y = info.dwSize.Y-1;
+ SetConsoleCursorPosition(handle, info.dwCursorPosition);
+ }
+ else if( *q == 'F' )
+ { // \033[#F - Cursor Preceding Line (CPL)
+ // Moves the cursor up the indicated # of rows, to column 1.
+ info.dwCursorPosition.Y -= (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F):1;
+ info.dwCursorPosition.X = 0;
+
+ if( info.dwCursorPosition.Y < 0 )
+ info.dwCursorPosition.Y = 0;
+ SetConsoleCursorPosition(handle, info.dwCursorPosition);
+ }
+ else if( *q == 'G' )
+ { // \033[#G - Cursor Horizontal Absolute (CHA)
+ // Moves the cursor to indicated column in current row.
+ info.dwCursorPosition.X = (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F-1):0;
+
+ if( info.dwCursorPosition.X >= info.dwSize.X )
+ info.dwCursorPosition.X = info.dwSize.X-1;
+ SetConsoleCursorPosition(handle, info.dwCursorPosition);
+ }
+ else if( *q == 'L' || *q == 'M' || *q == '@' || *q == 'P')
+ { // not implemented, just skip
+ }
+ else
+ { // no number nor valid sequencer
+ // something is fishy, we break and give the current char free
+ --q;
+ }
+ // skip the sequencer and search again
+ p = q+1;
+ break;
+ }// end while
+ }
+ }
+ if (*p) // write the rest of the buffer
+ if( 0==WriteConsole(handle, p, strlen(p), &written, 0) )
+ WriteFile(handle,p, strlen(p), &written, 0);
+ return 0;
+}
+
+int FPRINTF(HANDLE handle, const char *fmt, ...)
+{
+ int ret;
+ va_list argptr;
+ va_start(argptr, fmt);
+ ret = VFPRINTF(handle,fmt,argptr);
+ va_end(argptr);
+ return ret;
+}
+
+#define FFLUSH(handle)
+
+#define STDOUT GetStdHandle(STD_OUTPUT_HANDLE)
+#define STDERR GetStdHandle(STD_ERROR_HANDLE)
+
+#else // not _WIN32
+
+
+//#define VPRINTF vprintf
+//#define PRINTF printf
+
+#define is_console(file) (0!=isatty(fileno(file)))
+
+//vprintf_without_ansiformats
+int VFPRINTF(FILE *file, const char *fmt, va_list argptr)
+{
+ char *p, *q;
+
+ if(!fmt || !*fmt)
+ return 0;
+
+ if( is_console(file) || stdout_with_ansisequence )
+ {
+ vfprintf(file, fmt, argptr);
+ return 0;
+ }
+
+ if(tempbuf == NULL)
+ tempbuf_alloc();
+ for(; vsnprintf(tempbuf, tempbuf_size(), fmt, argptr)<0; tempbuf_realloc());
+ // vsnprintf returns -1 in case of insufficient buffer size
+ // tempbuf.realloc doubles the size of the buffer in this case
+
+ // start with processing
+ p = tempbuf;
+ while ((q = strchr(p, 0x1b)) != NULL)
+ { // find the escape character
+ fprintf(file, "%.*s", (int)(q-p), p); // write up to the escape
+ if( q[1]!='[' )
+ { // write the escape char (whatever purpose it has)
+ fprintf(file, "%.*s", 1, q);
+ p=q+1; //and start searching again
+ }
+ else
+ { // from here, we will skip the '\033['
+ // we break at the first unprocessible position
+ // assuming regular text is starting there
+
+ // skip escape and bracket
+ q=q+2;
+ while(1)
+ {
+ if( isdigit((int)((unsigned char)*q)) )
+ {
+ ++q;
+ // and next character
+ continue;
+ }
+ else if( *q == ';' )
+ { // delimiter
+ ++q;
+ // and next number
+ continue;
+ }
+ else if( *q == 'm' )
+ { // \033[#;...;#m - Set Graphics Rendition (SGR)
+ // set the attributes
+ }
+ else if( *q=='J' )
+ { // \033[#J - Erase Display (ED)
+ }
+ else if( *q=='K' )
+ { // \033[K : clear line from actual position to end of the line
+ }
+ else if( *q == 'H' || *q == 'f' )
+ { // \033[#;#H - Cursor Position (CUP)
+ // \033[#;#f - Horizontal & Vertical Position
+ }
+ else if( *q=='s' )
+ { // \033[s - Save Cursor Position (SCP)
+ }
+ else if( *q=='u' )
+ { // \033[u - Restore cursor position (RCP)
+ }
+ else if( *q == 'A' )
+ { // \033[#A - Cursor Up (CUU)
+ // Moves the cursor UP # number of lines
+ }
+ else if( *q == 'B' )
+ { // \033[#B - Cursor Down (CUD)
+ // Moves the cursor DOWN # number of lines
+ }
+ else if( *q == 'C' )
+ { // \033[#C - Cursor Forward (CUF)
+ // Moves the cursor RIGHT # number of columns
+ }
+ else if( *q == 'D' )
+ { // \033[#D - Cursor Backward (CUB)
+ // Moves the cursor LEFT # number of columns
+ }
+ else if( *q == 'E' )
+ { // \033[#E - Cursor Next Line (CNL)
+ // Moves the cursor down the indicated # of rows, to column 1
+ }
+ else if( *q == 'F' )
+ { // \033[#F - Cursor Preceding Line (CPL)
+ // Moves the cursor up the indicated # of rows, to column 1.
+ }
+ else if( *q == 'G' )
+ { // \033[#G - Cursor Horizontal Absolute (CHA)
+ // Moves the cursor to indicated column in current row.
+ }
+ else if( *q == 'L' || *q == 'M' || *q == '@' || *q == 'P')
+ { // not implemented, just skip
+ }
+ else
+ { // no number nor valid sequencer
+ // something is fishy, we break and give the current char free
+ --q;
+ }
+ // skip the sequencer and search again
+ p = q+1;
+ break;
+ }// end while
+ }
+ }
+ if (*p) // write the rest of the buffer
+ fprintf(file, "%s", p);
+ return 0;
+}
+int FPRINTF(FILE *file, const char *fmt, ...)
+{
+ int ret;
+ va_list argptr;
+ va_start(argptr, fmt);
+ ret = VFPRINTF(file,fmt,argptr);
+ va_end(argptr);
+ return ret;
+}
+
+#define FFLUSH fflush
+
+#define STDOUT stdout
+#define STDERR stderr
+
+#endif// not _WIN32
+
+
+
+
+
+
+
+
+
+
char timestamp_format[20] = ""; //For displaying Timestamps
+
// by MC Cameri
int _vShowMessage(enum msg_type flag, const char *string, va_list ap)
{
@@ -47,10 +651,18 @@ int _vShowMessage(enum msg_type flag, const char *string, va_list ap) FILE *fp;
#endif
- if (!string || strlen(string) <= 0) {
+ if (!string || *string == '\0') {
ShowError("Empty string passed to _vShowMessage().\n");
return 1;
}
+ if ((flag == MSG_DEBUG && !SHOW_DEBUG_MSG) ||
+ (flag == MSG_INFORMATION && msg_silent&1) ||
+ (flag == MSG_STATUS && msg_silent&2) ||
+ (flag == MSG_NOTICE && msg_silent&4) ||
+ (flag == MSG_WARNING && msg_silent&8) ||
+ (flag == MSG_ERROR && msg_silent&16) ||
+ (flag == MSG_SQL && msg_silent&16))
+ return 0; //Do not print it.
if (timestamp_format[0])
{ //Display time format. [Skotlex]
@@ -58,7 +670,6 @@ int _vShowMessage(enum msg_type flag, const char *string, va_list ap) strftime(prefix, 80, timestamp_format, localtime(&t));
} else prefix[0]='\0';
-
switch (flag) {
case MSG_NONE: // direct printf replacement
break;
@@ -91,60 +702,36 @@ int _vShowMessage(enum msg_type flag, const char *string, va_list ap) return 1;
}
- if ((flag == MSG_DEBUG && !SHOW_DEBUG_MSG) ||
- (flag == MSG_INFORMATION && msg_silent&1) ||
- (flag == MSG_STATUS && msg_silent&2) ||
- (flag == MSG_NOTICE && msg_silent&4) ||
- (flag == MSG_WARNING && msg_silent&8) ||
- (flag == MSG_ERROR && msg_silent&16) ||
- (flag == MSG_SQL && msg_silent&16)
- ) ; //Do not print it.
- else {
- if (flag == MSG_ERROR || flag == MSG_FATALERROR || flag == MSG_SQL)
- { //Send Errors to StdErr [Skotlex]
- fprintf (stderr, "%s ", prefix);
- vfprintf (stderr, string, ap);
- fflush (stderr);
- } else {
- if (flag != MSG_NONE)
- printf ("%s ", prefix);
- vprintf (string, ap);
- fflush (stdout);
- }
+ if (flag == MSG_ERROR || flag == MSG_FATALERROR || flag == MSG_SQL)
+ { //Send Errors to StdErr [Skotlex]
+ FPRINTF(STDERR, "%s ", prefix);
+ VFPRINTF(STDERR, string, ap);
+ FFLUSH(STDERR);
+ } else {
+ if (flag != MSG_NONE)
+ FPRINTF(STDOUT, "%s ", prefix);
+ VFPRINTF(STDOUT, string, ap);
+ FFLUSH(STDOUT);
}
#if defined(DEBUGLOGMAP) || defined(DEBUGLOGCHAR) || defined(DEBUGLOGLOGIN)
if(strlen(DEBUGLOGPATH) > 0) {
fp=fopen(DEBUGLOGPATH,"a");
if (fp == NULL) {
- printf(CL_RED"[ERROR]"CL_RESET": Could not open '"CL_WHITE"%s"CL_RESET"', access denied.\n",DEBUGLOGPATH);
- fflush(stdout);
- return 0;
+ FPRINTF(STDERR, CL_RED"[ERROR]"CL_RESET": Could not open '"CL_WHITE"%s"CL_RESET"', access denied.\n", DEBUGLOGPATH);
+ FFLUSH(STDERR);
+ } else {
+ fprintf(fp,"%s ", prefix);
+ vfprintf(fp,string,ap);
+ fclose(fp);
}
- fprintf(fp,"%s ", prefix);
- vfprintf(fp,string,ap);
- fclose(fp);
} else {
- printf(CL_RED"[ERROR]"CL_RESET": DEBUGLOGPATH not defined!\n");
+ FPRINTF(STDERR, CL_RED"[ERROR]"CL_RESET": DEBUGLOGPATH not defined!\n");
+ FFLUSH(STDERR);
}
#endif
va_end(ap);
-/*
- if ((core_config.debug_output_level > -1) && (flag >= core_config.debug_output_level)) {
- FILE *fp;
- fp=fopen(OUTPUT_MESSAGES_LOG,"a");
- if (fp == NULL) {
- ShowError("Could not open '"CL_WHITE"%s"CL_RESET"', file not found.\n",OUTPUT_MESSAGES_LOG);
- fflush(stdout);
- return;
- }
- StripColor(output);
- strcpy(output,"\r");
- fwrite(output,strlen(output),1,fp);
- fclose(fp);
- }
-*/
return 0;
}
@@ -156,64 +743,84 @@ void ClearScreen(void) }
int _ShowMessage(enum msg_type flag, const char *string, ...)
{
+ int ret;
va_list ap;
-
va_start(ap, string);
- return _vShowMessage(flag, string, ap);
+ ret = _vShowMessage(flag, string, ap);
+ va_end(ap);
+ return ret;
}
// direct printf replacement
int ShowMessage(const char *string, ...) {
+ int ret;
va_list ap;
-
va_start(ap, string);
- return _vShowMessage(MSG_NONE, string, ap);
+ ret = _vShowMessage(MSG_NONE, string, ap);
+ va_end(ap);
+ return ret;
}
int ShowStatus(const char *string, ...) {
+ int ret;
va_list ap;
-
va_start(ap, string);
- return _vShowMessage(MSG_STATUS, string, ap);
+ ret = _vShowMessage(MSG_STATUS, string, ap);
+ va_end(ap);
+ return ret;
}
int ShowSQL(const char *string, ...) {
+ int ret;
va_list ap;
-
va_start(ap, string);
- return _vShowMessage(MSG_SQL, string, ap);
+ ret = _vShowMessage(MSG_SQL, string, ap);
+ va_end(ap);
+ return ret;
}
int ShowInfo(const char *string, ...) {
+ int ret;
va_list ap;
-
va_start(ap, string);
- return _vShowMessage(MSG_INFORMATION, string, ap);
+ ret = _vShowMessage(MSG_INFORMATION, string, ap);
+ va_end(ap);
+ return ret;
}
int ShowNotice(const char *string, ...) {
+ int ret;
va_list ap;
-
va_start(ap, string);
- return _vShowMessage(MSG_NOTICE, string, ap);
+ ret = _vShowMessage(MSG_NOTICE, string, ap);
+ va_end(ap);
+ return ret;
}
int ShowWarning(const char *string, ...) {
+ int ret;
va_list ap;
-
va_start(ap, string);
- return _vShowMessage(MSG_WARNING, string, ap);
+ ret = _vShowMessage(MSG_WARNING, string, ap);
+ va_end(ap);
+ return ret;
}
int ShowDebug(const char *string, ...) {
+ int ret;
va_list ap;
-
va_start(ap, string);
- return _vShowMessage(MSG_DEBUG, string, ap);
+ ret = _vShowMessage(MSG_DEBUG, string, ap);
+ va_end(ap);
+ return ret;
}
-int ShowError(const char *string, ...) {
+int ShowError(const char *string, ...) {
+ int ret;
va_list ap;
-
va_start(ap, string);
- return _vShowMessage(MSG_ERROR, string, ap);
+ ret = _vShowMessage(MSG_ERROR, string, ap);
+ va_end(ap);
+ return ret;
}
int ShowFatalError(const char *string, ...) {
+ int ret;
va_list ap;
-
va_start(ap, string);
- return _vShowMessage(MSG_FATALERROR, string, ap);
+ ret = _vShowMessage(MSG_FATALERROR, string, ap);
+ va_end(ap);
+ return ret;
}
diff --git a/src/common/showmsg.h b/src/common/showmsg.h index c0112685a..f947b34e3 100644 --- a/src/common/showmsg.h +++ b/src/common/showmsg.h @@ -5,7 +5,6 @@ #define _SHOWMSG_H_
#define SHOW_DEBUG_MSG 1
-
// for help with the console colors look here:
// http://www.edoceo.com/liberum/?doc=printf-with-color
// some code explanation (used here):
@@ -14,53 +13,62 @@ // \033[0m : reset color parameter
// \033[1m : use bold for font
-#ifdef _WIN32
- #define CL_RESET ""
- #define CL_CLS ""
- #define CL_CLL ""
- #define CL_BOLD ""
- #define CL_NORMAL CL_RESET
- #define CL_NONE CL_RESET
- #define CL_WHITE ""
- #define CL_GRAY ""
- #define CL_RED ""
- #define CL_GREEN ""
- #define CL_YELLOW ""
- #define CL_BLUE ""
- #define CL_MAGENTA ""
- #define CL_CYAN ""
- #define CL_BT_YELLOW ""
- #define CL_WTBL ""
- #define CL_XXBL ""
- #define CL_PASS ""
-#else
- #define CL_RESET "\033[0;0m"
- #define CL_CLS "\033[2J"
- #define CL_CLL "\033[K"
+#define CL_RESET "\033[0m"
+#define CL_CLS "\033[2J"
+#define CL_CLL "\033[K"
- // font settings
- #define CL_BOLD "\033[1m"
- #define CL_NORMAL CL_RESET
- #define CL_NONE CL_RESET
+// font settings
+#define CL_BOLD "\033[1m"
+#define CL_NORM CL_RESET
+#define CL_NORMAL CL_RESET
+#define CL_NONE CL_RESET
+// foreground color and bold font (bright color on windows)
+#define CL_WHITE "\033[1;37m"
+#define CL_GRAY "\033[1;30m"
+#define CL_RED "\033[1;31m"
+#define CL_GREEN "\033[1;32m"
+#define CL_YELLOW "\033[1;33m"
+#define CL_BLUE "\033[1;34m"
+#define CL_MAGENTA "\033[1;35m"
+#define CL_CYAN "\033[1;36m"
- #define CL_WHITE "\033[1;37m"
- #define CL_GRAY "\033[1;30m"
- #define CL_RED "\033[1;31m"
- #define CL_GREEN "\033[1;32m"
- #define CL_YELLOW "\033[1;33m"
- #define CL_BLUE "\033[1;34m"
- #define CL_MAGENTA "\033[1;35m"
- #define CL_CYAN "\033[1;36m"
-
- #define CL_BT_YELLOW "\033[1;33m"
- #define CL_WTBL "\033[37;44m" // white on blue
- #define CL_XXBL "\033[0;44m" // default on blue
- #define CL_PASS "\033[0;32;42m" // green on green
-#endif
+// background color
+#define CL_BG_BLACK "\033[40m"
+#define CL_BG_RED "\033[41m"
+#define CL_BG_GREEN "\033[42m"
+#define CL_BG_YELLOW "\033[43m"
+#define CL_BG_BLUE "\033[44m"
+#define CL_BG_MAGENTA "\033[45m"
+#define CL_BG_CYAN "\033[46m"
+#define CL_BG_WHITE "\033[47m"
+// foreground color and normal font (normal color on windows)
+#define CL_LT_BLACK "\033[0;30m"
+#define CL_LT_RED "\033[0;31m"
+#define CL_LT_GREEN "\033[0;32m"
+#define CL_LT_YELLOW "\033[0;33m"
+#define CL_LT_BLUE "\033[0;34m"
+#define CL_LT_MAGENTA "\033[0;35m"
+#define CL_LT_CYAN "\033[0;36m"
+#define CL_LT_WHITE "\033[0;37m"
+// foreground color and bold font (bright color on windows)
+#define CL_BT_BLACK "\033[1;30m"
+#define CL_BT_RED "\033[1;31m"
+#define CL_BT_GREEN "\033[1;32m"
+#define CL_BT_YELLOW "\033[1;33m"
+#define CL_BT_BLUE "\033[1;34m"
+#define CL_BT_MAGENTA "\033[1;35m"
+#define CL_BT_CYAN "\033[1;36m"
+#define CL_BT_WHITE "\033[1;37m"
+
+#define CL_WTBL "\033[37;44m" // white on blue
+#define CL_XXBL "\033[0;44m" // default on blue
+#define CL_PASS "\033[0;32;42m" // green on green
+
+#define CL_SPACE " " // space aquivalent of the print messages
+extern int stdout_with_ansisequence; //If the color ansi sequences are to be used. [flaviojs]
extern int msg_silent; //Specifies how silent the console is. [Skotlex]
extern char timestamp_format[20]; //For displaying Timestamps [Skotlex]
-extern char tmp_output[1024];
enum msg_type {
MSG_NONE,
diff --git a/src/login/login.c b/src/login/login.c index ceb0448e4..038cff89b 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -3603,6 +3603,8 @@ int login_config_read(const char *cfgName) { if(strcmpi(w1,"timestamp_format") == 0) {
strncpy(timestamp_format, w2, 20);
+ } else if(strcmpi(w1,"stdout_with_ansisequence")==0){
+ stdout_with_ansisequence = config_switch(w2);
} else if(strcmpi(w1,"console_silent")==0){
msg_silent = 0; //To always allow the next line to show up.
ShowInfo("Console Silent Setting: %d\n", atoi(w2));
diff --git a/src/login_sql/login.c b/src/login_sql/login.c index 8dd0bcc48..903b38b35 100644 --- a/src/login_sql/login.c +++ b/src/login_sql/login.c @@ -2074,6 +2074,8 @@ int login_config_read(const char *cfgName){ remove_control_chars((unsigned char *) w2);
if(strcmpi(w1,"timestamp_format") == 0) {
strncpy(timestamp_format, w2, 20);
+ } else if(strcmpi(w1,"stdout_with_ansisequence")==0){
+ stdout_with_ansisequence = config_switch(w2);
} else if(strcmpi(w1,"console_silent")==0){
msg_silent = 0; //To always allow the next line to show up.
ShowInfo("Console Silent Setting: %d\n", atoi(w2));
diff --git a/src/map/map.c b/src/map/map.c index 52035d3bd..f55a85170 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -3292,6 +3292,18 @@ int parse_console(char *buf) { return 0; } +//------------------------------------------------- +// Return numerical value of a switch configuration +// on/off, english, franais, deutsch, espaol +//------------------------------------------------- +int config_switch(const char *str) { + if (strcmpi(str, "on") == 0 || strcmpi(str, "yes") == 0 || strcmpi(str, "oui") == 0 || strcmpi(str, "ja") == 0 || strcmpi(str, "si") == 0) + return 1; + if (strcmpi(str, "off") == 0 || strcmpi(str, "no") == 0 || strcmpi(str, "non") == 0 || strcmpi(str, "nein") == 0) + return 0; + return atoi(str); +} + /*========================================== * ݒt@C?? *------------------------------------------ @@ -3321,6 +3333,8 @@ int map_config_read(char *cfgName) { if(strcmpi(w1,"timestamp_format")==0){ strncpy(timestamp_format, w2, 20); + } else if(strcmpi(w1,"stdout_with_ansisequence")==0){ + stdout_with_ansisequence = config_switch(w2); } else if(strcmpi(w1,"console_silent")==0){ msg_silent = 0; //To always allow the next line to show up. ShowInfo("Console Silent Setting: %d\n", atoi(w2)); diff --git a/src/map/skill.c b/src/map/skill.c index ea9f44c4f..02c5e1e03 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -10087,8 +10087,13 @@ int skill_unit_move_sub (struct block_list *bl, va_list ap) } else { - if (flag&2 && skill_unit_index < 7) //Store this unit id. - skill_unit_temp[skill_unit_index++] = skill_id; + if (flag&2) { //Store this unit id. + if (skill_unit_index < 7) + skill_unit_temp[skill_unit_index++] = skill_id; + else if (battle_config.error_log) + ShowError("skill_unit_move_sub: Reached limit of unit objects per cell!\n"); + } + } if (flag&4) skill_unit_onleft(skill_id,target,tick); @@ -10112,8 +10117,12 @@ int skill_unit_move_sub (struct block_list *bl, va_list ap) else { result = skill_unit_onout(unit,target,tick); - if (flag&2 && skill_unit_index < 7 && result) //Store this unit id. - skill_unit_temp[skill_unit_index++] = result; + if (flag&2 && result) { //Store this unit id. + if (skill_unit_index < 7) + skill_unit_temp[skill_unit_index++] = result; + else if (battle_config.error_log) + ShowError("skill_unit_move_sub: Reached limit of unit objects per cell!\n"); + } } //TODO: Normally, this is dangerous since the unit and group could be freed diff --git a/src/map/status.c b/src/map/status.c index 6426eced3..f0b16afed 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -4825,6 +4825,16 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val break;
case SC_ENDURE:
val2 = 7; // Hit-count [Celest]
+ if (!(flag&1) && sd && !map_flag_gvg(bl->m))
+ {
+ struct map_session_data *tsd;
+ int i;
+ for (i = 0; i < 5; i++)
+ { //See if there are devoted characters, and pass the status to them. [Skotlex]
+ if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])))
+ status_change_start(&tsd->bl,type,10000,val1,val2,val3,val4,tick,1);
+ }
+ }
break;
case SC_AUTOBERSERK:
if (status->hp < status->max_hp>>2 &&
@@ -4884,14 +4894,14 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val break;
case SC_REFLECTSHIELD:
val2=10+val1*3; //% Dmg reflected
- if (sd)
+ if (sd && !(flag&1))
{ //Pass it to devoted chars.
struct map_session_data *tsd;
int i;
for (i = 0; i < 5; i++)
{ //Pass the status to the other affected chars. [Skotlex]
if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])))
- status_change_start(&tsd->bl,SC_AUTOGUARD,10000,val1,val2,0,0,tick,1);
+ status_change_start(&tsd->bl,type,10000,val1,val2,0,0,tick,1);
}
}
break;
@@ -5103,7 +5113,7 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val break;
case SC_AUTOGUARD:
- if (!flag)
+ if (!(flag&1))
{
struct map_session_data *tsd;
int i,t;
@@ -5115,13 +5125,13 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val for (i = 0; i < 5; i++)
{ //Pass the status to the other affected chars. [Skotlex]
if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])))
- status_change_start(&tsd->bl,SC_AUTOGUARD,10000,val1,val2,0,0,tick,1);
+ status_change_start(&tsd->bl,type,10000,val1,val2,0,0,tick,1);
}
}
break;
case SC_DEFENDER:
- if (!flag)
+ if (!(flag&1))
{
struct map_session_data *tsd;
int i;
@@ -5133,7 +5143,7 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val for (i = 0; i < 5; i++)
{ //See if there are devoted characters, and pass the status to them. [Skotlex]
if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])))
- status_change_start(&tsd->bl,SC_DEFENDER,10000,val1,5+val1*5,val3,val4,tick,1);
+ status_change_start(&tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,1);
}
}
break;
@@ -5361,16 +5371,16 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val { //Try to inherit the status from the Crusader [Skotlex]
//Ideally, we should calculate the remaining time and use that, but we'll trust that
//once the Crusader's status changes, it will reflect on the others.
- int type2 = SC_AUTOGUARD;
- if (src->sc.data[type2].timer != -1)
- sc_start(bl,type2,100,src->sc.data[type2].val1,skill_get_time(StatusSkillChangeTable[type2],src->sc.data[type2].val1));
- type2 = SC_DEFENDER;
- if (src->sc.data[type2].timer != -1)
- sc_start(bl,type2,100,src->sc.data[type2].val1,skill_get_time(StatusSkillChangeTable[type2],src->sc.data[type2].val1));
- type2 = SC_REFLECTSHIELD;
- if (src->sc.data[type2].timer != -1)
- sc_start(bl,type2,100,src->sc.data[type2].val1,skill_get_time(StatusSkillChangeTable[type2],src->sc.data[type2].val1));
-
+ const int types[] = { SC_AUTOGUARD, SC_DEFENDER, SC_REFLECTSHIELD, SC_ENDURE };
+ int type2;
+ int i = map_flag_gvg(bl->m)?2:3;
+ while (i >= 0) {
+ type2 = types[i];
+ if (src->sc.data[type2].timer != -1)
+ sc_start(bl,type2,100,src->sc.data[type2].val1,
+ skill_get_time(StatusSkillChangeTable[type2],src->sc.data[type2].val1));
+ i--;
+ }
}
break;
}
@@ -5992,6 +6002,7 @@ int status_change_end( struct block_list* bl , int type,int tid ) case SC_DEFENDER:
case SC_REFLECTSHIELD:
case SC_AUTOGUARD:
+ case SC_ENDURE:
if (sd) {
struct map_session_data *tsd;
int i;
@@ -6011,13 +6022,15 @@ int status_change_end( struct block_list* bl , int type,int tid ) md->devotion[sc->data[type].val2] = 0;
clif_devotion(md);
}
- //Remove AutoGuard and Defender [Skotlex]
+ //Remove inherited status [Skotlex]
if (sc->data[SC_AUTOGUARD].timer != -1)
status_change_end(bl,SC_AUTOGUARD,-1);
if (sc->data[SC_DEFENDER].timer != -1)
status_change_end(bl,SC_DEFENDER,-1);
if (sc->data[SC_REFLECTSHIELD].timer != -1)
status_change_end(bl,SC_REFLECTSHIELD,-1);
+ if (sc->data[SC_ENDURE].timer != -1)
+ status_change_end(bl,SC_ENDURE,-1);
break;
}
case SC_BLADESTOP:
|