summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt13
-rw-r--r--conf-tmpl/Changelog.txt6
-rw-r--r--conf-tmpl/char_athena.conf8
-rw-r--r--conf-tmpl/login_athena.conf8
-rw-r--r--conf-tmpl/map_athena.conf8
-rw-r--r--src/char/char.c2
-rw-r--r--src/char_sql/char.c2
-rw-r--r--src/common/showmsg.c739
-rw-r--r--src/common/showmsg.h94
-rw-r--r--src/login/login.c2
-rw-r--r--src/login_sql/login.c2
-rw-r--r--src/map/map.c14
-rw-r--r--src/map/skill.c17
-rw-r--r--src/map/status.c47
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: